diff --git a/api/_balance.ts b/api/_balance.ts index 87b396cb3..a2b49d87e 100644 --- a/api/_balance.ts +++ b/api/_balance.ts @@ -63,7 +63,7 @@ export async function getBalance( ); } -async function getSvmBalance( +export async function getSvmBalance( chainId: string | number, account: string, token: string diff --git a/api/_constants.ts b/api/_constants.ts index 1dddd5fc0..15f9daa7e 100644 --- a/api/_constants.ts +++ b/api/_constants.ts @@ -378,6 +378,14 @@ export const CUSTOM_GAS_TOKENS = { [CHAIN_IDs.HYPERCORE]: "HYPE", }; +export const EVM_CHAIN_IDs = Object.entries(constants.PUBLIC_NETWORKS) + .filter(([_, chain]) => chain.family !== constants.ChainFamily.SVM) + .map(([chainId]) => Number(chainId)); + +export const SVM_CHAIN_IDs = Object.entries(constants.PUBLIC_NETWORKS) + .filter(([_, chain]) => chain.family === constants.ChainFamily.SVM) + .map(([chainId]) => Number(chainId)); + export const STABLE_COIN_SYMBOLS = Array.from( new Set([ ...sdkConstants.STABLE_COIN_SYMBOLS, diff --git a/api/_providers.ts b/api/_providers.ts index f0a19e3d3..c71c37040 100644 --- a/api/_providers.ts +++ b/api/_providers.ts @@ -210,3 +210,16 @@ export function getProviderHeaders( return rpcHeaders?.[String(chainId)]; } + +/** + * Gets the Alchemy RPC URL for a given chain ID from the rpc-providers.json configuration + * @param chainId The chain ID to get the Alchemy RPC URL for + * @returns The Alchemy RPC URL or undefined if not available + */ +export function getAlchemyRpcFromConfigJson( + chainId: number +): string | undefined { + const { providers } = rpcProvidersJson; + const alchemyUrls = providers.urls.alchemy as Record; + return alchemyUrls?.[String(chainId)]; +} diff --git a/api/swap/tokens/_service.ts b/api/swap/tokens/_service.ts new file mode 100644 index 000000000..b5edd4322 --- /dev/null +++ b/api/swap/tokens/_service.ts @@ -0,0 +1,298 @@ +import axios from "axios"; +import { constants } from "ethers"; +import mainnetChains from "../../../src/data/chains_1.json"; +import indirectChains from "../../../src/data/indirect_chains_1.json"; +import { CHAIN_IDs, TOKEN_SYMBOLS_MAP } from "../../_constants"; +import { + ENABLED_ROUTES, + getChainInfo, + getFallbackTokenLogoURI, +} from "../../_utils"; + +export type SwapToken = { + chainId: number; + address: string; + name: string; + symbol: string; + decimals: number; + logoUrl: string; + priceUsd: string | null; +}; + +const chains = mainnetChains; +const chainIds = [...chains, ...indirectChains].map((chain) => chain.chainId); + +function getUniswapTokens( + uniswapResponse: any, + chainIds: number[], + pricesForLifiTokens: Record> +): SwapToken[] { + return uniswapResponse.tokens.reduce((acc: SwapToken[], token: any) => { + if (chainIds.includes(token.chainId)) { + acc.push({ + chainId: token.chainId, + address: token.address, + name: token.name, + symbol: token.symbol, + decimals: token.decimals, + logoUrl: token.logoURI, + priceUsd: pricesForLifiTokens[token.chainId]?.[token.address] || null, + }); + } + return acc; + }, []); +} + +function getNativeTokensFromLifiTokens( + lifiTokensResponse: any, + chainIds: number[], + pricesForLifiTokens: Record> +): SwapToken[] { + return chainIds.reduce((acc: SwapToken[], chainId) => { + const nativeToken = lifiTokensResponse?.tokens?.[chainId]?.find( + (token: any) => token.address === constants.AddressZero + ); + if (nativeToken) { + acc.push({ + chainId, + address: nativeToken.address, + name: nativeToken.name, + symbol: nativeToken.symbol, + decimals: nativeToken.decimals, + logoUrl: nativeToken.logoURI, + priceUsd: pricesForLifiTokens[chainId]?.[nativeToken.address] || null, + }); + } + return acc; + }, []); +} + +function getPricesForLifiTokens(lifiTokensResponse: any, chainIds: number[]) { + return chainIds.reduce( + (acc, chainId) => { + const tokens = lifiTokensResponse.tokens[chainId]; + if (!tokens) { + return acc; + } + tokens.forEach((token: any) => { + if (!acc[chainId]) { + acc[chainId] = {}; + } + acc[chainId][token.address] = token.priceUSD; + }); + return acc; + }, + {} as Record> + ); +} + +function getJupiterTokens( + jupiterTokensResponse: any[], + chainIds: number[] +): SwapToken[] { + if (!chainIds.includes(CHAIN_IDs.SOLANA)) { + return []; + } + + return jupiterTokensResponse.reduce((acc: SwapToken[], token: any) => { + if (token.organicScoreLabel === "high") { + acc.push({ + chainId: CHAIN_IDs.SOLANA, + address: token.id, + name: token.name, + symbol: token.symbol, + decimals: token.decimals, + logoUrl: token.icon, + priceUsd: token.usdPrice?.toString() || null, + }); + } + return acc; + }, []); +} + +function getIndirectChainTokens( + chainIds: number[], + pricesForLifiTokens: Record> +): SwapToken[] { + // Chain ID to use for token price lookups + const PRICE_LOOKUP_CHAIN_ID = CHAIN_IDs.MAINNET; + + return indirectChains.flatMap((chain) => { + if (!chainIds.includes(chain.chainId)) { + return []; + } + + return chain.outputTokens.map((token) => { + // Try to resolve price using L1 address from TOKEN_SYMBOLS_MAP + let priceUsd: string | null = null; + const tokenInfo = + TOKEN_SYMBOLS_MAP[token.symbol as keyof typeof TOKEN_SYMBOLS_MAP]; + + if (tokenInfo) { + // Get L1 address + const l1Address = tokenInfo.addresses[PRICE_LOOKUP_CHAIN_ID]; + if (l1Address) { + priceUsd = + pricesForLifiTokens[PRICE_LOOKUP_CHAIN_ID]?.[l1Address] || null; + } + } + + return { + chainId: chain.chainId, + address: token.address, + name: token.name, + symbol: token.symbol, + decimals: token.decimals, + logoUrl: token.logoUrl, + priceUsd, + }; + }); + }); +} + +function getTokensFromEnabledRoutes( + chainIds: number[], + pricesForLifiTokens: Record> +): SwapToken[] { + const tokens: SwapToken[] = []; + const seenTokens = new Set(); + + const addToken = ( + chainId: number, + tokenSymbol: string, + tokenAddress: string, + l1TokenAddress: string, + isNative: boolean + ) => { + const finalAddress = isNative ? constants.AddressZero : tokenAddress; + + const tokenKey = `${chainId}-${tokenSymbol}-${finalAddress.toLowerCase()}`; + + // Only add each unique token once + if (!seenTokens.has(tokenKey)) { + seenTokens.add(tokenKey); + + const tokenInfo = + TOKEN_SYMBOLS_MAP[tokenSymbol as keyof typeof TOKEN_SYMBOLS_MAP]; + + tokens.push({ + chainId, + address: finalAddress, + name: tokenInfo.name, + symbol: tokenSymbol, + decimals: tokenInfo.decimals, + logoUrl: getFallbackTokenLogoURI(l1TokenAddress), + priceUsd: pricesForLifiTokens[chainId]?.[finalAddress] || null, + }); + } + }; + + ENABLED_ROUTES.routes.forEach((route) => { + // Process origin tokens (fromChain) + if (chainIds.includes(route.fromChain)) { + addToken( + route.fromChain, + route.fromTokenSymbol, + route.fromTokenAddress, + route.l1TokenAddress, + route.isNative + ); + } + + // Process destination tokens (toChain) + if (chainIds.includes(route.toChain)) { + // For destination tokens, check if token is native on that chain + const chainInfo = getChainInfo(route.toChain); + const nativeSymbol = + route.toChain === CHAIN_IDs.LENS ? "GHO" : chainInfo.nativeToken; + const isDestinationNative = route.toTokenSymbol === nativeSymbol; + + addToken( + route.toChain, + route.toTokenSymbol, + route.toTokenAddress, + route.l1TokenAddress, + isDestinationNative + ); + } + }); + + return tokens; +} + +function deduplicateTokens(tokens: SwapToken[]): SwapToken[] { + const seen = new Map(); + + tokens.forEach((token) => { + const key = `${token.chainId}-${token.symbol}-${token.address.toLowerCase()}`; + + // Keep first occurrence + if (!seen.has(key)) { + seen.set(key, token); + } + }); + + return Array.from(seen.values()); +} + +export async function fetchSwapTokensData( + filteredChainIds?: number[] +): Promise { + const targetChainIds = filteredChainIds || chainIds; + + const [uniswapTokensResponse, lifiTokensResponse, jupiterTokensResponse] = + await Promise.all([ + axios.get("https://tokens.uniswap.org"), + axios.get("https://li.quest/v1/tokens"), + axios.get("https://lite-api.jup.ag/tokens/v2/toporganicscore/24h"), + ]); + + const pricesForLifiTokens = getPricesForLifiTokens( + lifiTokensResponse.data, + targetChainIds + ); + + const responseJson: SwapToken[] = []; + + // Add Uniswap tokens + const uniswapTokens = getUniswapTokens( + uniswapTokensResponse.data, + targetChainIds, + pricesForLifiTokens + ); + responseJson.push(...uniswapTokens); + + // Add native tokens from LiFi + const nativeTokens = getNativeTokensFromLifiTokens( + lifiTokensResponse.data, + targetChainIds, + pricesForLifiTokens + ); + responseJson.push(...nativeTokens); + + // Add Jupiter tokens + const jupiterTokens = getJupiterTokens( + jupiterTokensResponse.data, + targetChainIds + ); + responseJson.push(...jupiterTokens); + + // Add tokens from indirect chains (e.g., USDT-SPOT on HyperCore) + const indirectChainTokens = getIndirectChainTokens( + targetChainIds, + pricesForLifiTokens + ); + responseJson.push(...indirectChainTokens); + + // Add tokens from Across' enabled routes (fills gaps from external sources) + const tokensFromEnabledRoutes = getTokensFromEnabledRoutes( + targetChainIds, + pricesForLifiTokens + ); + responseJson.push(...tokensFromEnabledRoutes); + + // Deduplicate tokens (external sources take precedence) + const deduplicatedTokens = deduplicateTokens(responseJson); + + return deduplicatedTokens; +} diff --git a/api/swap/tokens/index.ts b/api/swap/tokens/index.ts index c8f28d76a..953704ea1 100644 --- a/api/swap/tokens/index.ts +++ b/api/swap/tokens/index.ts @@ -1,37 +1,18 @@ import { VercelResponse } from "@vercel/node"; -import axios from "axios"; -import { constants } from "ethers"; import { type, assert, Infer, optional, array, union } from "superstruct"; -import { CHAIN_IDs, TOKEN_SYMBOLS_MAP } from "../../_constants"; -import { getRequestId, setRequestSpanAttributes } from "../../_request_utils"; -import { sendResponse } from "../../_response_utils"; -import { TypedVercelRequest } from "../../_types"; import { - ENABLED_ROUTES, - getChainInfo, - getFallbackTokenLogoURI, getLogger, handleErrorCondition, paramToArray, positiveIntStr, } from "../../_utils"; -import { tracer, processor } from "../../../instrumentation"; -import mainnetChains from "../../../src/data/chains_1.json"; -import indirectChains from "../../../src/data/indirect_chains_1.json"; - -type Token = { - chainId: number; - address: string; - name: string; - symbol: string; - decimals: number; - logoUrl: string; - priceUsd: string | null; -}; +import { TypedVercelRequest } from "../../_types"; -const chains = mainnetChains; -const chainIds = [...chains, ...indirectChains].map((chain) => chain.chainId); +import { getRequestId, setRequestSpanAttributes } from "../../_request_utils"; +import { sendResponse } from "../../_response_utils"; +import { tracer, processor } from "../../../instrumentation"; +import { fetchSwapTokensData, SwapToken } from "./_service"; const SwapTokensQueryParamsSchema = type({ chainId: optional(union([positiveIntStr(), array(positiveIntStr())])), @@ -59,70 +40,20 @@ export default async function handler( const { chainId } = query; const filteredChainIds = chainId - ? paramToArray(chainId)?.map(Number) || chainIds - : chainIds; - - const [uniswapTokensResponse, lifiTokensResponse, jupiterTokensResponse] = - await Promise.all([ - axios.get("https://tokens.uniswap.org"), - axios.get("https://li.quest/v1/tokens"), - axios.get("https://lite-api.jup.ag/tokens/v2/toporganicscore/24h"), - ]); - const pricesForLifiTokens = getPricesForLifiTokens( - lifiTokensResponse.data, - filteredChainIds - ); - - const responseJson: Token[] = []; - - // Add Uniswap tokens - const uniswapTokens = getUniswapTokens( - uniswapTokensResponse.data, - filteredChainIds, - pricesForLifiTokens - ); - responseJson.push(...uniswapTokens); - - // Add native tokens from LiFi - const nativeTokens = getNativeTokensFromLifiTokens( - lifiTokensResponse.data, - filteredChainIds, - pricesForLifiTokens - ); - responseJson.push(...nativeTokens); - - // Add Jupiter tokens - const jupiterTokens = getJupiterTokens( - jupiterTokensResponse.data, - filteredChainIds - ); - responseJson.push(...jupiterTokens); + ? paramToArray(chainId)?.map(Number) + : undefined; - // Add tokens from indirect chains (e.g., USDT-SPOT on HyperCore) - const indirectChainTokens = getIndirectChainTokens( - filteredChainIds, - pricesForLifiTokens - ); - responseJson.push(...indirectChainTokens); - - // Add tokens from Across' enabled routes (fills gaps from external sources) - const tokensFromEnabledRoutes = getTokensFromEnabledRoutes( - filteredChainIds, - pricesForLifiTokens - ); - responseJson.push(...tokensFromEnabledRoutes); - - // Deduplicate tokens (external sources take precedence) - const deduplicatedTokens = deduplicateTokens(responseJson); + const responseJson: SwapToken[] = + await fetchSwapTokensData(filteredChainIds); logger.debug({ at: "swap/tokens", message: "Response data", - responseJson: deduplicatedTokens, + responseJson, }); sendResponse({ response, - body: deduplicatedTokens, + body: responseJson, statusCode: 200, requestId, cacheSeconds: 60 * 5, @@ -143,216 +74,3 @@ export default async function handler( } }); } - -function getUniswapTokens( - uniswapResponse: any, - chainIds: number[], - pricesForLifiTokens: Record> -): Token[] { - return uniswapResponse.tokens.reduce((acc: Token[], token: any) => { - if (chainIds.includes(token.chainId)) { - acc.push({ - chainId: token.chainId, - address: token.address, - name: token.name, - symbol: token.symbol, - decimals: token.decimals, - logoUrl: token.logoURI, - priceUsd: pricesForLifiTokens[token.chainId]?.[token.address] || null, - }); - } - return acc; - }, []); -} - -function getNativeTokensFromLifiTokens( - lifiTokensResponse: any, - chainIds: number[], - pricesForLifiTokens: Record> -): Token[] { - return chainIds.reduce((acc: Token[], chainId) => { - const nativeToken = lifiTokensResponse?.tokens?.[chainId]?.find( - (token: any) => token.address === constants.AddressZero - ); - if (nativeToken) { - acc.push({ - chainId, - address: nativeToken.address, - name: nativeToken.name, - symbol: nativeToken.symbol, - decimals: nativeToken.decimals, - logoUrl: nativeToken.logoURI, - priceUsd: pricesForLifiTokens[chainId]?.[nativeToken.address] || null, - }); - } - return acc; - }, []); -} - -function getPricesForLifiTokens(lifiTokensResponse: any, chainIds: number[]) { - return chainIds.reduce( - (acc, chainId) => { - const tokens = lifiTokensResponse.tokens[chainId]; - if (!tokens) { - return acc; - } - tokens.forEach((token: any) => { - if (!acc[chainId]) { - acc[chainId] = {}; - } - acc[chainId][token.address] = token.priceUSD; - }); - return acc; - }, - {} as Record> - ); // chainId -> tokenAddress -> price -} - -function getJupiterTokens( - jupiterTokensResponse: any[], - chainIds: number[] -): Token[] { - if (!chainIds.includes(CHAIN_IDs.SOLANA)) { - return []; - } - - return jupiterTokensResponse.reduce((acc: Token[], token: any) => { - if (token.organicScoreLabel === "high") { - acc.push({ - chainId: CHAIN_IDs.SOLANA, - address: token.id, - name: token.name, - symbol: token.symbol, - decimals: token.decimals, - logoUrl: token.icon, - priceUsd: token.usdPrice?.toString() || null, - }); - } - return acc; - }, []); -} - -function getIndirectChainTokens( - chainIds: number[], - pricesForLifiTokens: Record> -): Token[] { - // Chain ID to use for token price lookups - const PRICE_LOOKUP_CHAIN_ID = CHAIN_IDs.MAINNET; - - return indirectChains.flatMap((chain) => { - if (!chainIds.includes(chain.chainId)) { - return []; - } - - return chain.outputTokens.map((token) => { - // Try to resolve price using L1 address from TOKEN_SYMBOLS_MAP - let priceUsd: string | null = null; - const tokenInfo = - TOKEN_SYMBOLS_MAP[token.symbol as keyof typeof TOKEN_SYMBOLS_MAP]; - - if (tokenInfo) { - // Get L1 address - const l1Address = tokenInfo.addresses[PRICE_LOOKUP_CHAIN_ID]; - if (l1Address) { - priceUsd = - pricesForLifiTokens[PRICE_LOOKUP_CHAIN_ID]?.[l1Address] || null; - } - } - - return { - chainId: chain.chainId, - address: token.address, - name: token.name, - symbol: token.symbol, - decimals: token.decimals, - logoUrl: token.logoUrl, - priceUsd, - }; - }); - }); -} - -function getTokensFromEnabledRoutes( - chainIds: number[], - pricesForLifiTokens: Record> -): Token[] { - const tokens: Token[] = []; - const seenTokens = new Set(); - - const addToken = ( - chainId: number, - tokenSymbol: string, - tokenAddress: string, - l1TokenAddress: string, - isNative: boolean - ) => { - const finalAddress = isNative ? constants.AddressZero : tokenAddress; - - const tokenKey = `${chainId}-${tokenSymbol}-${finalAddress.toLowerCase()}`; - - // Only add each unique token once - if (!seenTokens.has(tokenKey)) { - seenTokens.add(tokenKey); - - const tokenInfo = - TOKEN_SYMBOLS_MAP[tokenSymbol as keyof typeof TOKEN_SYMBOLS_MAP]; - - tokens.push({ - chainId, - address: finalAddress, - name: tokenInfo.name, - symbol: tokenSymbol, - decimals: tokenInfo.decimals, - logoUrl: getFallbackTokenLogoURI(l1TokenAddress), - priceUsd: pricesForLifiTokens[chainId]?.[finalAddress] || null, - }); - } - }; - - ENABLED_ROUTES.routes.forEach((route) => { - // Process origin tokens (fromChain) - if (chainIds.includes(route.fromChain)) { - addToken( - route.fromChain, - route.fromTokenSymbol, - route.fromTokenAddress, - route.l1TokenAddress, - route.isNative - ); - } - - // Process destination tokens (toChain) - if (chainIds.includes(route.toChain)) { - // For destination tokens, check if token is native on that chain - const chainInfo = getChainInfo(route.toChain); - const nativeSymbol = - route.toChain === CHAIN_IDs.LENS ? "GHO" : chainInfo.nativeToken; - const isDestinationNative = route.toTokenSymbol === nativeSymbol; - - addToken( - route.toChain, - route.toTokenSymbol, - route.toTokenAddress, - route.l1TokenAddress, - isDestinationNative - ); - } - }); - - return tokens; -} - -function deduplicateTokens(tokens: Token[]): Token[] { - const seen = new Map(); - - tokens.forEach((token) => { - const key = `${token.chainId}-${token.symbol}-${token.address.toLowerCase()}`; - - // Keep first occurrence - if (!seen.has(key)) { - seen.set(key, token); - } - }); - - return Array.from(seen.values()); -} diff --git a/api/user-token-balances/_evm.ts b/api/user-token-balances/_evm.ts new file mode 100644 index 000000000..ef72b0d5a --- /dev/null +++ b/api/user-token-balances/_evm.ts @@ -0,0 +1,258 @@ +import { BigNumber, ethers } from "ethers"; +import { getLogger } from "../_utils"; +import { getAlchemyRpcFromConfigJson } from "../_providers"; +import { SwapToken } from "../swap/tokens/_service"; + +const logger = getLogger(); + +export function getTokenAddressesForChain( + swapTokens: SwapToken[], + chainId: number +): string[] { + const tokens = swapTokens + .filter((token) => token.chainId === chainId) + .map((token) => token.address); + + return Array.from(new Set(tokens)); +} + +export async function fetchNativeBalance( + chainId: number, + account: string, + rpcUrl: string +): Promise { + try { + logger.debug({ + at: "fetchNativeBalance", + message: "Fetching native balance", + chainId, + account, + }); + + const response = await fetch(rpcUrl, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: 1, + method: "eth_getBalance", + params: [account, "latest"], + }), + }); + + if (!response.ok) { + logger.warn({ + at: "fetchNativeBalance", + message: "HTTP error fetching native balance", + chainId, + status: response.status, + statusText: response.statusText, + }); + return null; + } + + const data = await response.json(); + + if (!data || !data.result) { + logger.warn({ + at: "fetchNativeBalance", + message: "Invalid response for native balance", + chainId, + responseData: data, + }); + return null; + } + + return BigNumber.from(data.result).toString(); + } catch (error) { + logger.warn({ + at: "fetchNativeBalance", + message: "Error fetching native balance", + chainId, + error: error instanceof Error ? error.message : String(error), + }); + return null; + } +} + +export async function fetchErc20Balances( + chainId: number, + account: string, + tokenAddresses: string[], + rpcUrl: string +): Promise> { + // Early return if no token addresses + if (tokenAddresses.length === 0) { + logger.debug({ + at: "fetchErc20Balances", + message: "No ERC20 token addresses to fetch, returning empty array", + chainId, + }); + return []; + } + + try { + const response = await fetch(rpcUrl, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: 1, + method: "alchemy_getTokenBalances", + params: [account, tokenAddresses], + }), + }); + + logger.debug({ + at: "fetchErc20Balances", + message: "Making request to Alchemy API for ERC20 tokens", + chainId, + account, + rpcUrl, + tokenAddressCount: tokenAddresses.length, + }); + + if (!response.ok) { + logger.warn({ + at: "fetchErc20Balances", + message: "HTTP error from Alchemy API, returning empty balances", + chainId, + status: response.status, + statusText: response.statusText, + }); + return []; + } + + const data = await response.json(); + + logger.debug({ + at: "fetchErc20Balances", + message: "Received response from Alchemy API", + chainId, + responseData: data, + }); + + // Validate the response structure + if (!data || !data.result || !data.result.tokenBalances) { + logger.warn({ + at: "fetchErc20Balances", + message: "Invalid response from Alchemy API, returning empty balances", + chainId, + responseData: data, + }); + return []; + } + + const erc20Balances = ( + data.result.tokenBalances as { + contractAddress: string; + tokenBalance: string; + }[] + ) + .filter((t) => { + if (!t.tokenBalance) return false; + try { + const balance = BigNumber.from(t.tokenBalance); + // Filter out zero balances and MaxUint256 (Alchemy sometimes borks and returns MaxUint256) + return balance.gt(0) && balance.lt(ethers.constants.MaxUint256); + } catch (error) { + logger.warn({ + at: "fetchErc20Balances", + message: "Invalid token balance value", + chainId, + tokenAddress: t.contractAddress, + tokenBalance: t.tokenBalance, + }); + return false; + } + }) + .map((t) => ({ + address: t.contractAddress, + balance: BigNumber.from(t.tokenBalance).toString(), + })); + + return erc20Balances; + } catch (error) { + logger.warn({ + at: "fetchErc20Balances", + message: "Error fetching ERC20 balances from Alchemy API", + chainId, + error: error instanceof Error ? error.message : String(error), + }); + return []; + } +} + +export async function fetchTokenBalancesForChain( + chainId: number, + account: string, + tokenAddresses: string[] +): Promise<{ + chainId: number; + balances: Array<{ address: string; balance: string }>; +}> { + const rpcUrl = getAlchemyRpcFromConfigJson(chainId); + + if (!rpcUrl) { + logger.warn({ + at: "fetchTokenBalancesForChain", + message: "No Alchemy RPC URL found for chain, returning empty balances", + chainId, + }); + return { + chainId, + balances: [], + }; + } + + try { + // Separate ERC20 tokens from native token + const erc20TokenAddresses = tokenAddresses.filter( + (addr) => addr !== ethers.constants.AddressZero + ); + + logger.debug({ + at: "fetchTokenBalancesForChain", + message: "Fetching token balances for chain", + chainId, + totalTokens: tokenAddresses.length, + erc20Tokens: erc20TokenAddresses.length, + }); + + // Fetch both ERC20 and native balances in parallel + const [erc20Balances, nativeBalance] = await Promise.all([ + fetchErc20Balances(chainId, account, erc20TokenAddresses, rpcUrl), + fetchNativeBalance(chainId, account, rpcUrl), + ]); + + // Add native balance if it exists and is greater than 0 + const balances = [...erc20Balances]; + if (nativeBalance && BigNumber.from(nativeBalance).gt(0)) { + balances.unshift({ + address: ethers.constants.AddressZero, + balance: nativeBalance, + }); + } + + return { + chainId, + balances, + }; + } catch (error) { + logger.warn({ + at: "fetchTokenBalancesForChain", + message: + "Error fetching token balances from Alchemy API, returning empty balances", + chainId, + error: error instanceof Error ? error.message : String(error), + }); + return { + chainId, + balances: [], + }; + } +} diff --git a/api/user-token-balances/_service.ts b/api/user-token-balances/_service.ts new file mode 100644 index 000000000..5b0aef021 --- /dev/null +++ b/api/user-token-balances/_service.ts @@ -0,0 +1,141 @@ +import { MAINNET_CHAIN_IDs } from "@across-protocol/constants"; +import * as sdk from "@across-protocol/sdk"; +import { getLogger } from "../_utils"; +import { getAlchemyRpcFromConfigJson } from "../_providers"; +import { isSvmAddress } from "../_address"; +import { fetchSwapTokensData, SwapToken } from "../swap/tokens/_service"; +import { CHAIN_IDs, EVM_CHAIN_IDs } from "../_constants"; +import * as evmService from "./_evm"; +import * as svmService from "./_svm"; + +const logger = getLogger(); + +async function getSwapTokens( + filteredChainIds?: number[] +): Promise { + try { + return await fetchSwapTokensData(filteredChainIds); + } catch (error) { + logger.warn({ + at: "getSwapTokens", + message: "Failed to fetch swap tokens", + error: error instanceof Error ? error.message : String(error), + }); + return []; + } +} + +function getEvmChainIds(): number[] { + return Object.values(MAINNET_CHAIN_IDs) + .filter((chainId) => !sdk.utils.chainIsSvm(chainId)) + .filter((chainId) => !!getAlchemyRpcFromConfigJson(chainId)) + .sort((a, b) => a - b); +} + +function getSvmChainIds(): number[] { + return Object.values(MAINNET_CHAIN_IDs) + .filter((chainId) => sdk.utils.chainIsSvm(chainId)) + .sort((a, b) => a - b); +} + +export const handleUserTokenBalances = async (account: string) => { + // Check if the account is a Solana address + const isSolanaAddress = isSvmAddress(account); + + if (isSolanaAddress) { + // For SVM addresses, fetch all SVM chain balances + logger.debug({ + at: "handleUserTokenBalances", + message: "Detected SVM address, fetching SVM balances", + account, + }); + + const svmChainIds = getSvmChainIds(); + + // Fetch swap tokens to get the list of token addresses for each chain + const swapTokens = await getSwapTokens([CHAIN_IDs.SOLANA]); + + logger.debug({ + at: "handleUserTokenBalances", + message: "Fetched swap tokens for SVM", + tokenCount: swapTokens.length, + }); + + // Fetch balances for all SVM chains in parallel + const balancePromises = svmChainIds.map((chainId) => { + const tokenAddresses = svmService.getSvmTokenAddressesForChain( + swapTokens, + chainId + ); + logger.debug({ + at: "handleUserTokenBalances", + message: "Token addresses for SVM chain", + chainId, + tokenAddressCount: tokenAddresses.length, + }); + return svmService.fetchTokenBalancesForChain( + chainId, + account, + tokenAddresses + ); + }); + + const chainBalances = await Promise.all(balancePromises); + + return { + account, + balances: chainBalances.map(({ chainId, balances }) => ({ + chainId: chainId.toString(), + balances, + })), + }; + } + + // For EVM addresses, fetch all EVM chain balances + logger.debug({ + at: "handleUserTokenBalances", + message: "Detected EVM address, fetching EVM balances", + account, + }); + + // Get all available EVM chain IDs that have Alchemy RPC URLs + const chainIdsAvailable = getEvmChainIds(); + + // Fetch swap tokens to get the list of token addresses for each chain + const swapTokens = await getSwapTokens(EVM_CHAIN_IDs); + + logger.debug({ + at: "handleUserTokenBalances", + message: "Fetched swap tokens", + tokenCount: swapTokens.length, + }); + + // Fetch balances for all chains in parallel + const balancePromises = chainIdsAvailable.map((chainId) => { + const tokenAddresses = evmService.getTokenAddressesForChain( + swapTokens, + chainId + ); + logger.debug({ + at: "handleUserTokenBalances", + message: "Token addresses for chain", + chainId, + tokenAddressCount: tokenAddresses.length, + }); + return evmService.fetchTokenBalancesForChain( + chainId, + account, + tokenAddresses + ); + }); + + const chainBalances = await Promise.all(balancePromises); + + return { + account, + balances: chainBalances.map(({ chainId, balances }) => ({ + chainId: chainId.toString(), + balances, + })), + }; +}; diff --git a/api/user-token-balances/_svm.ts b/api/user-token-balances/_svm.ts new file mode 100644 index 000000000..8fe5bebaa --- /dev/null +++ b/api/user-token-balances/_svm.ts @@ -0,0 +1,157 @@ +import { BigNumber } from "ethers"; +import * as sdk from "@across-protocol/sdk"; +import { getLogger } from "../_utils"; +import { getSvmBalance } from "../_balance"; +import { SwapToken } from "../swap/tokens/_service"; + +const logger = getLogger(); + +export function getSvmTokenAddressesForChain( + swapTokens: SwapToken[], + chainId: number +): string[] { + const tokens = swapTokens + .filter((token) => token.chainId === chainId) + .map((token) => token.address); + + return Array.from(new Set(tokens)); +} + +export async function fetchNativeBalance( + chainId: number, + account: string +): Promise { + try { + logger.debug({ + at: "fetchNativeBalance", + message: "Fetching native SVM balance", + chainId, + account, + }); + + const balance = await getSvmBalance( + chainId, + account, + sdk.constants.ZERO_ADDRESS + ); + + return balance.toString(); + } catch (error) { + logger.warn({ + at: "fetchNativeBalance", + message: "Error fetching native SVM balance", + chainId, + error: error instanceof Error ? error.message : String(error), + }); + return null; + } +} + +export async function fetchSplTokenBalances( + chainId: number, + account: string, + tokenAddresses: string[] +): Promise> { + // Early return if no token addresses + if (tokenAddresses.length === 0) { + logger.debug({ + at: "fetchSplTokenBalances", + message: "No SPL token addresses to fetch, returning empty array", + chainId, + }); + return []; + } + + logger.debug({ + at: "fetchSplTokenBalances", + message: "Fetching SPL token balances", + chainId, + account, + tokenAddressCount: tokenAddresses.length, + }); + + // Fetch balances for all tokens in parallel + const balancePromises = tokenAddresses.map(async (tokenAddress) => { + try { + const balance = await getSvmBalance(chainId, account, tokenAddress); + return { + address: tokenAddress, + balance: balance.toString(), + }; + } catch (error) { + logger.warn({ + at: "fetchSplTokenBalances", + message: "Error fetching balance for SPL token", + chainId, + tokenAddress, + error: error instanceof Error ? error.message : String(error), + }); + return null; + } + }); + + const results = await Promise.all(balancePromises); + + // Filter out null results and zero balances + const balances = results.filter( + (result): result is { address: string; balance: string } => + result !== null && BigNumber.from(result.balance).gt(0) + ); + + return balances; +} + +export async function fetchTokenBalancesForChain( + chainId: number, + account: string, + tokenAddresses: string[] +): Promise<{ + chainId: number; + balances: Array<{ address: string; balance: string }>; +}> { + try { + // Separate SPL tokens from native token + const splTokenAddresses = tokenAddresses.filter( + (addr) => addr !== sdk.constants.ZERO_ADDRESS + ); + + logger.debug({ + at: "fetchTokenBalancesForChain", + message: "Fetching token balances for chain", + chainId, + totalTokens: tokenAddresses.length, + splTokens: splTokenAddresses.length, + }); + + // Fetch both SPL tokens and native balance in parallel + const [splBalances, nativeBalance] = await Promise.all([ + fetchSplTokenBalances(chainId, account, splTokenAddresses), + fetchNativeBalance(chainId, account), + ]); + + // Add native balance if it exists and is greater than 0 + const balances = [...splBalances]; + if (nativeBalance && BigNumber.from(nativeBalance).gt(0)) { + balances.unshift({ + address: sdk.constants.ZERO_ADDRESS, + balance: nativeBalance, + }); + } + + return { + chainId, + balances, + }; + } catch (error) { + logger.warn({ + at: "fetchTokenBalancesForChain", + message: "Error fetching SVM token balances, returning empty balances", + chainId, + error: error instanceof Error ? error.message : String(error), + }); + return { + chainId, + balances: [], + }; + } +} diff --git a/api/user-token-balances/index.ts b/api/user-token-balances/index.ts new file mode 100644 index 000000000..d79cea396 --- /dev/null +++ b/api/user-token-balances/index.ts @@ -0,0 +1,71 @@ +import { VercelResponse } from "@vercel/node"; +import { assert, Infer, type } from "superstruct"; +import { TypedVercelRequest } from "../_types"; +import { getLogger, handleErrorCondition, validAddress } from "../_utils"; +import { handleUserTokenBalances } from "./_service"; +import { getRequestId, setRequestSpanAttributes } from "../_request_utils"; +import { sendResponse } from "../_response_utils"; +import { tracer, processor } from "../../instrumentation"; + +const UserTokenBalancesQueryParamsSchema = type({ + account: validAddress(), +}); + +type UserTokenBalancesQueryParams = Infer< + typeof UserTokenBalancesQueryParamsSchema +>; + +const handler = async ( + request: TypedVercelRequest, + response: VercelResponse +) => { + const logger = getLogger(); + const requestId = getRequestId(request); + logger.debug({ + at: "user-token-balances", + message: "Request data", + requestId, + }); + + return tracer.startActiveSpan("user-token-balances", async (span) => { + setRequestSpanAttributes(request, span, requestId); + + try { + const { query } = request; + assert(query, UserTokenBalancesQueryParamsSchema); + const { account } = query; + + const responseData = await handleUserTokenBalances(account); + + logger.debug({ + at: "user-token-balances", + message: "Response data", + responseJson: responseData, + requestId, + }); + + sendResponse({ + response, + body: responseData, + statusCode: 200, + requestId, + cacheSeconds: 10, // 30 seconds cache - balances update frequently after transactions + staleWhileRevalidateSeconds: 10, + }); + } catch (error: unknown) { + return handleErrorCondition( + "user-token-balances", + response, + logger, + error, + span, + requestId + ); + } finally { + span.end(); + processor.forceFlush(); + } + }); +}; + +export default handler; diff --git a/package.json b/package.json index e6df110f0..428cd62be 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "license": "AGPL-3.0-only", "dependencies": { "@across-protocol/constants": "^3.1.82", - "@across-protocol/contracts": "^4.1.11", + "@across-protocol/contracts": "^4.1.12", "@across-protocol/contracts-v4.1.1": "npm:@across-protocol/contracts@4.1.1", "@across-protocol/sdk": "^4.3.88", "@amplitude/analytics-browser": "^2.3.5", @@ -38,6 +38,7 @@ "@tanstack/react-query": "v5", "@tanstack/react-query-devtools": "v5", "@types/bn.js": "^5.1.6", + "@uidotdev/usehooks": "^2.4.1", "@uniswap/sdk-core": "^7.7.2", "@uniswap/smart-order-router": "^4.22.16", "@uniswap/v3-sdk": "^3.25.2", @@ -54,6 +55,7 @@ "react": "v18", "react-dom": "v18", "react-feather": "^2.0.9", + "react-hotkeys-hook": "^5.1.0", "react-pro-sidebar": "^1.1.0", "react-router-dom": "v5", "react-tooltip": "^5.18.0", @@ -67,9 +69,10 @@ "dev": "export REACT_APP_GIT_COMMIT_HASH=$(git rev-parse HEAD) && vite --port $PORT --host", "dev:api": "vercel dev --listen 127.0.0.1:3000", "build": "tsc && vite build", - "prebuild": "export REACT_APP_GIT_COMMIT_HASH=$(git rev-parse HEAD) && yarn remote-config && yarn remote-env", + "prebuild": "export REACT_APP_GIT_COMMIT_HASH=$(git rev-parse HEAD) && yarn remote-config && yarn remote-env && yarn cache-swap-tokens", "remote-config": "tsx scripts/fetch-remote-config.ts", "remote-env": "tsx ./scripts/fetch-remote-env.ts", + "cache-swap-tokens": "tsx scripts/cache-swap-tokens.ts", "analyze": "yarn build && rollup-plugin-visualizer --open ./bundle-size-analysis.json", "test": "export REACT_APP_GIT_COMMIT_HASH=$(git rev-parse HEAD) && jest --config jest.frontend.config.cjs", "serve": "vite preview --port 3000", diff --git a/public/fonts/Barlow-ExtraBold.woff2 b/public/fonts/Barlow-ExtraBold.woff2 new file mode 100644 index 000000000..6174634d1 Binary files /dev/null and b/public/fonts/Barlow-ExtraBold.woff2 differ diff --git a/public/fonts/Barlow-ExtraLight.woff2 b/public/fonts/Barlow-ExtraLight.woff2 new file mode 100644 index 000000000..bf655c4f2 Binary files /dev/null and b/public/fonts/Barlow-ExtraLight.woff2 differ diff --git a/public/fonts/Barlow-Light.woff2 b/public/fonts/Barlow-Light.woff2 new file mode 100644 index 000000000..5dd45ebd9 Binary files /dev/null and b/public/fonts/Barlow-Light.woff2 differ diff --git a/public/fonts/Barlow-SemiBold.woff2 b/public/fonts/Barlow-SemiBold.woff2 new file mode 100644 index 000000000..52681ea89 Binary files /dev/null and b/public/fonts/Barlow-SemiBold.woff2 differ diff --git a/public/fonts/Barlow-Thin.woff2 b/public/fonts/Barlow-Thin.woff2 new file mode 100644 index 000000000..1e40c2a59 Binary files /dev/null and b/public/fonts/Barlow-Thin.woff2 differ diff --git a/scripts/cache-swap-tokens.ts b/scripts/cache-swap-tokens.ts new file mode 100644 index 000000000..f722472f7 --- /dev/null +++ b/scripts/cache-swap-tokens.ts @@ -0,0 +1,44 @@ +import { writeFileSync, mkdirSync } from "fs"; +import { join } from "path"; +import { fetchSwapTokensData, SwapToken } from "../api/swap/tokens/_service"; + +export interface SwapTokensCache { + tokens: SwapToken[]; + timestamp: number; + version: string; +} + +async function main() { + try { + console.log("Fetching swap tokens data..."); + const tokens = await fetchSwapTokensData(); + + // Create cache directory if it doesn't exist + const cacheDir = join(process.cwd(), "src", "data"); + mkdirSync(cacheDir, { recursive: true }); + + // Write cached tokens to file + const cacheFile = join(cacheDir, "swap-tokens.json"); + const cacheData: SwapTokensCache = { + tokens, + timestamp: Date.now(), + version: "1.0.0", + }; + + writeFileSync(cacheFile, JSON.stringify(cacheData, null, 2)); + + console.log( + `✅ Successfully cached ${tokens.length} swap tokens to ${cacheFile}` + ); + console.log( + `📊 Cache size: ${Math.round(JSON.stringify(cacheData).length / 1024)}KB` + ); + } catch (error) { + console.error("❌ Failed to cache swap tokens:", error); + process.exit(1); + } +} + +if (require.main === module) { + main(); +} diff --git a/src/Routes.tsx b/src/Routes.tsx index 911bfadb3..37c82718e 100644 --- a/src/Routes.tsx +++ b/src/Routes.tsx @@ -8,14 +8,9 @@ import { } from "react-router-dom"; import { Header, Sidebar } from "components"; import { useConnection, useError } from "hooks"; -import { - enableMigration, - stringValueInArray, - getConfig, - chainEndpointToId, -} from "utils"; +import { stringValueInArray, getConfig, chainEndpointToId } from "utils"; import lazyWithRetry from "utils/lazy-with-retry"; - +import { enableMigration } from "utils"; import Toast from "components/Toast"; import BouncingDotsLoader from "components/BouncingDotsLoader"; import NotFound from "./views/NotFound"; @@ -23,6 +18,15 @@ import ScrollToTop from "components/ScrollToTop"; import { AmpliTrace } from "components/AmpliTrace"; import Banners from "components/Banners"; +export const NAVIGATION_LINKS = !enableMigration + ? [ + { href: "/bridge-and-swap", name: "Bridge & Swap" }, + { href: "/pool", name: "Pool" }, + { href: "/rewards", name: "Rewards" }, + { href: "/transactions", name: "Transactions" }, + ] + : []; + const LiquidityPool = lazyWithRetry( () => import(/* webpackChunkName: "LiquidityPools" */ "./views/LiquidityPool") ); @@ -50,6 +54,9 @@ const Transactions = lazyWithRetry( const Staking = lazyWithRetry( () => import(/* webpackChunkName: "RewardStaking" */ "./views/Staking") ); +const SwapAndBridge = lazyWithRetry( + () => import(/* webpackChunkName: "RewardStaking" */ "./views/SwapAndBridge") +); const DepositStatus = lazyWithRetry(() => import("./views/DepositStatus")); function useRoutes() { @@ -137,13 +144,28 @@ const Routes: React.FC = () => { } }} /> - - + + + + ( + + )} + /> diff --git a/src/assets/chain-logos/all-swap-chain.png b/src/assets/chain-logos/all-swap-chain.png new file mode 100644 index 000000000..787d5e385 Binary files /dev/null and b/src/assets/chain-logos/all-swap-chain.png differ diff --git a/src/assets/icons/arrow-down.svg b/src/assets/icons/arrow-down.svg new file mode 100644 index 000000000..f9f930a98 --- /dev/null +++ b/src/assets/icons/arrow-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/arrow-up-right-boxed.svg b/src/assets/icons/arrow-up-right-boxed.svg index c0b442de5..be7dfb05a 100644 --- a/src/assets/icons/arrow-up-right-boxed.svg +++ b/src/assets/icons/arrow-up-right-boxed.svg @@ -1,3 +1,3 @@ - + diff --git a/src/assets/icons/arrows-cross.svg b/src/assets/icons/arrows-cross.svg new file mode 100644 index 000000000..5df5e97f1 --- /dev/null +++ b/src/assets/icons/arrows-cross.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/icons/checkmark-circle-filled.svg b/src/assets/icons/checkmark-circle-filled.svg new file mode 100644 index 000000000..36a6867ec --- /dev/null +++ b/src/assets/icons/checkmark-circle-filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/dollar.svg b/src/assets/icons/dollar.svg new file mode 100644 index 000000000..fa7dcf539 --- /dev/null +++ b/src/assets/icons/dollar.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icons/gas.svg b/src/assets/icons/gas.svg new file mode 100644 index 000000000..bba1d5579 --- /dev/null +++ b/src/assets/icons/gas.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icons/info.svg b/src/assets/icons/info.svg index b913e3bbf..6ff5bf813 100644 --- a/src/assets/icons/info.svg +++ b/src/assets/icons/info.svg @@ -1,5 +1,5 @@ - - - - + + + + diff --git a/src/assets/icons/loading-2.svg b/src/assets/icons/loading-2.svg new file mode 100644 index 000000000..547982fb3 --- /dev/null +++ b/src/assets/icons/loading-2.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/icons/pencil.svg b/src/assets/icons/pencil.svg new file mode 100644 index 000000000..78c27820d --- /dev/null +++ b/src/assets/icons/pencil.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/product.svg b/src/assets/icons/product.svg new file mode 100644 index 000000000..a370c74fb --- /dev/null +++ b/src/assets/icons/product.svg @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/research.svg b/src/assets/icons/research.svg new file mode 100644 index 000000000..065b3b72c --- /dev/null +++ b/src/assets/icons/research.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icons/route.svg b/src/assets/icons/route.svg new file mode 100644 index 000000000..8671c3c4b --- /dev/null +++ b/src/assets/icons/route.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/search.svg b/src/assets/icons/search.svg new file mode 100644 index 000000000..908f1c03d --- /dev/null +++ b/src/assets/icons/search.svg @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/search_results.svg b/src/assets/icons/search_results.svg new file mode 100644 index 000000000..fec5b3cfe --- /dev/null +++ b/src/assets/icons/search_results.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/assets/icons/shield.svg b/src/assets/icons/shield.svg new file mode 100644 index 000000000..503c3a2e5 --- /dev/null +++ b/src/assets/icons/shield.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/siren.svg b/src/assets/icons/siren.svg new file mode 100644 index 000000000..b616bd545 --- /dev/null +++ b/src/assets/icons/siren.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/icons/time.svg b/src/assets/icons/time.svg new file mode 100644 index 000000000..055c9a2b4 --- /dev/null +++ b/src/assets/icons/time.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icons/wallet.svg b/src/assets/icons/wallet.svg index 37c3b159d..9bc251d8a 100644 --- a/src/assets/icons/wallet.svg +++ b/src/assets/icons/wallet.svg @@ -1,5 +1,5 @@ - - - - + + + + diff --git a/src/assets/icons/warning_triangle.svg b/src/assets/icons/warning_triangle.svg new file mode 100644 index 000000000..4cd75e33f --- /dev/null +++ b/src/assets/icons/warning_triangle.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/warning_triangle_filled.svg b/src/assets/icons/warning_triangle_filled.svg new file mode 100644 index 000000000..762ee642c --- /dev/null +++ b/src/assets/icons/warning_triangle_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/mask/token-mask-corner.svg b/src/assets/mask/token-mask-corner.svg new file mode 100644 index 000000000..1b89f0b41 --- /dev/null +++ b/src/assets/mask/token-mask-corner.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/mask/token-mask.svg b/src/assets/mask/token-mask.svg new file mode 100644 index 000000000..b968415b0 --- /dev/null +++ b/src/assets/mask/token-mask.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/token-logos/fallback.svg b/src/assets/token-logos/fallback.svg new file mode 100644 index 000000000..82cde45e5 --- /dev/null +++ b/src/assets/token-logos/fallback.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/token-logos/hype.svg b/src/assets/token-logos/hype.svg new file mode 100644 index 000000000..35f596fe8 --- /dev/null +++ b/src/assets/token-logos/hype.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/token-logos/sol.svg b/src/assets/token-logos/sol.svg new file mode 100644 index 000000000..a1a56cbdb --- /dev/null +++ b/src/assets/token-logos/sol.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/components/AmountInput/AmountInput.tsx b/src/components/AmountInput/AmountInput.tsx index 7c45b8e71..a424345e3 100644 --- a/src/components/AmountInput/AmountInput.tsx +++ b/src/components/AmountInput/AmountInput.tsx @@ -7,6 +7,7 @@ import { IconPair } from "components/IconPair"; import { Text } from "components/Text"; import { Tooltip } from "components/Tooltip"; import { Input, InputGroup } from "components/Input"; +import { TokenImage } from "components/TokenImage"; import { useTokenConversion } from "hooks/useTokenConversion"; import { QUERIESV2, @@ -81,13 +82,23 @@ export function AmountInput({ token.logoURIs?.length === 2 ? ( } - RightIcon={} + LeftIcon={ + + } + RightIcon={ + + } iconSize={16} /> ) : ( - + ) ) : null} {`${rightTokenSymbol} + } iconSize={24} /> @@ -66,7 +70,7 @@ const StyledAssetCell = styled(BaseCell)` } `; -const TokenIconImg = styled.img` +const TokenIconImg = styled(TokenImage)` width: 32px; height: 32px; diff --git a/src/components/DepositsTable/cells/RewardsCell.tsx b/src/components/DepositsTable/cells/RewardsCell.tsx index 7904f21cc..acabe9c19 100644 --- a/src/components/DepositsTable/cells/RewardsCell.tsx +++ b/src/components/DepositsTable/cells/RewardsCell.tsx @@ -1,6 +1,7 @@ import styled from "@emotion/styled"; import { Text } from "components/Text"; +import { TokenImage } from "components/TokenImage"; import { Deposit } from "hooks/useDeposits"; import { @@ -22,7 +23,7 @@ export function RewardsCell({ deposit, width }: Props) { {deposit.rewards && rewardToken ? ( <> - {rewardToken.symbol} + {formatUnitsWithMaxFractions( deposit.rewards.amount, diff --git a/src/components/Dialogs/Dialog.tsx b/src/components/Dialogs/Dialog.tsx new file mode 100644 index 000000000..d5d7a3b30 --- /dev/null +++ b/src/components/Dialogs/Dialog.tsx @@ -0,0 +1,236 @@ +import Modal from "components/Modal"; +import { ModalProps } from "components/Modal/Modal"; +import styled from "@emotion/styled"; +import { COLORS, QUERIES, withOpacity } from "utils"; +import { ReactComponent as Warning } from "assets/icons/warning_triangle_filled.svg"; +import { ReactComponent as Siren } from "assets/icons/siren.svg"; +import { ReactComponent as Info } from "assets/icons/info.svg"; +import { PropsWithChildren } from "react"; + +type Variant = "warn" | "error" | "info"; + +const defaultIcons: Record = { + warn: , + error: , + info: , +}; + +const defaultColors: Record = { + warn: "rgba(255, 149, 0, 1)", + error: COLORS.error, + info: COLORS.white, +}; + +// DialogWrapper - The main container that wraps everything +export type DialogWrapperProps = ModalProps & { + className?: string; +}; + +export function DialogWrapper({ + children, + className, + ...props +}: DialogWrapperProps) { + return ( + + {children} + + ); +} + +// DialogIcon - For displaying icons with variant-based styling +export type DialogIconProps = { + variant?: Variant; + icon?: React.ReactNode; + color?: string; + className?: string; +}; + +export function DialogIcon({ + variant = "info", + icon, + color, + className, +}: DialogIconProps) { + const Icon = icon ?? defaultIcons[variant]; + const iconColor = color ?? defaultColors[variant]; + + return ( + + {Icon} + + ); +} + +// DialogContent - For the main content area +export type DialogContentProps = { + children: React.ReactNode; + className?: string; +}; + +export function DialogContent({ children, className }: DialogContentProps) { + return {children}; +} + +// DialogButtonRow - Container for buttons +export type DialogButtonRowProps = { + children: React.ReactNode; + className?: string; +}; + +export function DialogButtonRow({ children, className }: DialogButtonRowProps) { + return {children}; +} + +// DialogButtonPrimary - Primary action button +export type DialogButtonPrimaryProps = { + children?: React.ReactNode; + onClick?: () => void; + className?: string; +}; + +export function DialogButtonPrimary({ + children, + onClick, + className, +}: DialogButtonPrimaryProps) { + return ( + + {children} + + ); +} + +// DialogButtonSecondary - Secondary action button +export type DialogButtonSecondaryProps = { + children?: React.ReactNode; + onClick?: () => void; + className?: string; +}; + +export function DialogButtonSecondary({ + children, + onClick, + className, +}: DialogButtonSecondaryProps) { + return ( + + {children} + + ); +} + +// Legacy Dialog component for backward compatibility +export type DoYourOwnResearchDialogProps = ModalProps & { + variant: Variant; + primaryAction?: () => void; + secondaryAction?: () => void; + icon?: React.ReactNode; + color?: string; + className?: string; +}; + +export function Dialog({ + children, + className, + variant, + icon, + primaryAction, + secondaryAction, + ...props +}: DoYourOwnResearchDialogProps) { + const Icon = icon ?? defaultIcons[variant]; + return ( + + {Icon} + {children} + {(secondaryAction || primaryAction) && ( + + {secondaryAction && } + {primaryAction && } + + )} + + ); +} + +// Styled components +const ButtonRow = styled.div` + display: flex; + gap: 16px; + justify-content: center; + width: 100%; + align-items: center; + flex-direction: column; + flex-wrap: wrap; + + @media ${QUERIES.tabletAndUp} { + flex-direction: row; + } +`; + +const PrimaryButton = styled.button` + display: flex; + height: 48px; + width: auto; + padding: 0 var(--Spacing-Medium, 16px); + justify-content: center; + align-items: center; + border-radius: 12px; + background: rgba(224, 243, 255, 0.1); + cursor: pointer; + color: white; + border: 1px solid transparent; + flex: 1 0 auto; + font-size: 16px; + font-weight: 600; + + &:hover { + background: none; + border: 1px solid rgba(224, 243, 255, 0.1); + } +`; + +const SecondaryButton = styled(PrimaryButton)` + background: transparent; + border: 1px solid rgba(224, 243, 255, 0.1); + + &:hover { + background: rgba(224, 243, 255, 0.1); + border-color: transparent; + } +`; + +const Wrapper = styled(Modal)` + width: 100%; + max-width: 450px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + gap: 12px; +`; + +const IconWrapper = styled.div<{ color: string }>` + background-color: ${({ color }) => withOpacity(color, 0.2)}; + border-radius: 50%; + width: 56px; + height: 56px; + display: flex; + align-items: center; + justify-content: center; + + svg { + width: 32px; + height: 32px; + color: ${({ color }) => color}; + } +`; + +const ContentWrapper = styled.div` + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; +`; diff --git a/src/components/GlobalStyles/GlobalStyles.tsx b/src/components/GlobalStyles/GlobalStyles.tsx index bf4d75d9d..43d5626f4 100644 --- a/src/components/GlobalStyles/GlobalStyles.tsx +++ b/src/components/GlobalStyles/GlobalStyles.tsx @@ -3,6 +3,36 @@ import { reset } from "./reset"; export const typography = css` /* only take latin chars to reduce bundle size */ + @font-face { + font-family: "Barlow"; + font-style: normal; + font-weight: 100; + font-display: fallback; + src: url("/fonts/Barlow-Thin.woff2") format("woff2"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, + U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, + U+2212, U+2215, U+FEFF, U+FFFD; + } + @font-face { + font-family: "Barlow"; + font-style: normal; + font-weight: 200; + font-display: fallback; + src: url("/fonts/Barlow-ExtraLight.woff2") format("woff2"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, + U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, + U+2212, U+2215, U+FEFF, U+FFFD; + } + @font-face { + font-family: "Barlow"; + font-style: normal; + font-weight: 300; + font-display: fallback; + src: url("/fonts/Barlow-Light.woff2") format("woff2"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, + U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, + U+2212, U+2215, U+FEFF, U+FFFD; + } @font-face { font-family: "Barlow"; font-style: normal; @@ -23,6 +53,16 @@ export const typography = css` U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } + @font-face { + font-family: "Barlow"; + font-style: normal; + font-weight: 600; + font-display: fallback; + src: url("/fonts/Barlow-SemiBold.woff2") format("woff2"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, + U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, + U+2212, U+2215, U+FEFF, U+FFFD; + } @font-face { font-family: "Barlow"; font-style: normal; @@ -33,6 +73,16 @@ export const typography = css` U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } + @font-face { + font-family: "Barlow"; + font-style: normal; + font-weight: 800; + font-display: fallback; + src: url("/fonts/Barlow-ExtraBold.woff2") format("woff2"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, + U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, + U+2212, U+2215, U+FEFF, U+FFFD; + } `; const variables = css` :root { @@ -84,6 +134,88 @@ const variables = css` --tints-shades-white-100: #e0f3ff; --tints-shades-white-200: #9daab2; + /* Color tokens (from Figma) */ + --base-aqua: var(--shades-aqua-aqua-300); + --base-bright-gray: var(--shades-neutrals-neutral-100); + --base-dark-gray: var(--shades-neutrals-neutral-800); + --functional-blue: #47a8ff; + --functional-red: #ff6166; + --functional-yellow: #ff9500; + --shades-aqua-aqua-100: #bdfced; + --shades-aqua-aqua-200: #98fbe4; + --shades-aqua-aqua-300: #6cf9d8; + --shades-aqua-aqua-400: #66e5c7; + --shades-aqua-aqua-500: #59bca6; + --shades-aqua-aqua-600: #4d9385; + --shades-aqua-aqua-700: #406b65; + --shades-aqua-aqua-800: #3a5754; + --shades-aqua-aqua-900: #334244; + --shades-neutrals-neutral-000: #ffffff; + --shades-neutrals-neutral-100: #e0f3ff; + --shades-neutrals-neutral-200: #cedfeb; + --shades-neutrals-neutral-300: #aab8c2; + --shades-neutrals-neutral-400: #869099; + --shades-neutrals-neutral-500: #636970; + --shades-neutrals-neutral-600: #51555c; + --shades-neutrals-neutral-700: #3f4247; + --shades-neutrals-neutral-800: #2d2e33; + --shades-neutrals-neutral-850: #34353b; + --shades-neutrals-neutral-900: #202024; + --transparency-aqua-aqua-10: #6cf9d81a; + --transparency-aqua-aqua-20: #6cf9d833; + --transparency-aqua-aqua-30: #6cf9d84d; + --transparency-aqua-aqua-40: #6cf9d866; + --transparency-aqua-aqua-5: #6cf9d80d; + --transparency-aqua-aqua-50: #6cf9d880; + --transparency-aqua-aqua-60: #6cf9d899; + --transparency-aqua-aqua-70: #6cf9d8b2; + --transparency-aqua-aqua-80: #6cf9d8cc; + --transparency-aqua-aqua-90: #6cf9d8e5; + --transparency-bright-gray-bright-gray-10: #e0f3ff1a; + --transparency-bright-gray-bright-gray-20: #e0f3ff33; + --transparency-bright-gray-bright-gray-30: #e0f3ff4d; + --transparency-bright-gray-bright-gray-40: #e0f3ff66; + --transparency-bright-gray-bright-gray-5: #e0f3ff0d; + --transparency-bright-gray-bright-gray-50: #e0f3ff80; + --transparency-bright-gray-bright-gray-60: #e0f3ff99; + --transparency-bright-gray-bright-gray-70: #e0f3ffb2; + --transparency-bright-gray-bright-gray-80: #e0f3ffcc; + --transparency-bright-gray-bright-gray-90: #e0f3ffe5; + --transparency-dark-gray-dark-gray-10: #2d2e331a; + --transparency-dark-gray-dark-gray-20: #2d2e3333; + --transparency-dark-gray-dark-gray-30: #2d2e334d; + --transparency-dark-gray-dark-gray-40: #2d2e3366; + --transparency-dark-gray-dark-gray-5: #2d2e330d; + --transparency-dark-gray-dark-gray-50: #2d2e3380; + --transparency-dark-gray-dark-gray-60: #2d2e3399; + --transparency-dark-gray-dark-gray-70: #2d2e33b2; + --transparency-dark-gray-dark-gray-80: #2d2e33cc; + --transparency-dark-gray-dark-gray-90: #2d2e33e5; + + /* Spacing tokens (from Figma) */ + --corner-radius-none: 0px; + --corner-radius-3x-small: 4px; + --corner-radius-2x-small: 6px; + --corner-radius-x-small: 8px; + --corner-radius-small: 12px; + --corner-radius-medium: 16px; + --corner-radius-large: 24px; + --corner-radius-x-large: 32px; + --corner-radius-2x-large: 40px; + --corner-radius-round: 999px; + --spacing-none: 0px; + --spacing-3x-small: 4px; + --spacing-2x-small: 6px; + --spacing-x-small: 8px; + --spacing-small: 12px; + --spacing-medium: 16px; + --spacing-large: 24px; + --spacing-x-large: 32px; + --spacing-2x-large: 40px; + --spacing-3x-large: 64px; + --spacing-4x-large: 80px; + --spacing-5x-large: 120px; + /* Old variables kept until refactored */ --color-primary: var(--color-interface-aqua); --color-gray: var(--color-neutrals-black-800); @@ -105,6 +237,17 @@ const globalStyles = css` -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: auto; } + button { + border: none; + background: none; + color: inherit; + } + button:not(:disabled) { + cursor: pointer; + } + button:disabled { + cursor: not-allowed; + } html, body { min-height: 100vh; diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index 3ab13f5ef..051bfb9f9 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -13,19 +13,12 @@ import { StyledLogo, } from "./Header.styles"; import MenuToggle from "./MenuToggle"; -import { enableMigration } from "utils"; import useScrollPosition from "hooks/useScrollPosition"; import { isChildPath } from "./utils"; import { useSidebarContext } from "hooks/useSidebarContext"; +import { NAVIGATION_LINKS } from "Routes"; -const LINKS = !enableMigration - ? [ - { href: "/bridge", name: "Bridge" }, - { href: "/pool", name: "Pool" }, - { href: "/rewards", name: "Rewards" }, - { href: "/transactions", name: "Transactions" }, - ] - : []; +export const LINKS = NAVIGATION_LINKS; interface Props { transparentHeader?: boolean; diff --git a/src/components/Input/index.tsx b/src/components/Input/index.tsx index 0bc7cd940..9acb03c10 100644 --- a/src/components/Input/index.tsx +++ b/src/components/Input/index.tsx @@ -1,4 +1,5 @@ import styled from "@emotion/styled"; +import { forwardRef } from "react"; import { COLORS, QUERIESV2 } from "utils"; @@ -21,12 +22,14 @@ export const colorMap = { }, }; -export function Input({ - validationLevel, - ...props -}: IValidInput & React.InputHTMLAttributes) { - return ; -} +export const Input = forwardRef< + HTMLInputElement, + IValidInput & React.ComponentPropsWithoutRef<"input"> +>(({ validationLevel, ...props }, ref) => { + return ; +}); + +Input.displayName = "Input"; export function InputGroup({ validationLevel, @@ -38,6 +41,7 @@ export function InputGroup({ const StyledInput = styled.input` font-weight: 400; font-size: 18px; + font-size: 16px; line-height: 26px; color: ${({ validationLevel }) => colorMap[validationLevel].text}; background: none; @@ -49,7 +53,6 @@ const StyledInput = styled.input` &:focus { outline: 0; - font-size: 18px; } &::placeholder { @@ -82,6 +85,14 @@ const InputGroupWrapper = styled.div` gap: 8px; width: 100%; + &:has(:focus-visible) { + border-color: ${COLORS.aqua}; + } + + &:focus-within { + border-color: ${COLORS.aqua}; + } + @media ${QUERIESV2.sm.andDown} { padding: 6px 12px 6px 24px; } diff --git a/src/components/Modal/Modal.styles.ts b/src/components/Modal/Modal.styles.ts index 90ffe8db1..f343061c8 100644 --- a/src/components/Modal/Modal.styles.ts +++ b/src/components/Modal/Modal.styles.ts @@ -1,7 +1,6 @@ import { keyframes } from "@emotion/react"; import styled from "@emotion/styled"; -import { ReactComponent as CrossIcon } from "assets/icons/cross.svg"; -import { QUERIESV2 } from "utils"; +import { COLORS, QUERIES, QUERIESV2 } from "utils"; import { ModalDirection } from "./Modal"; const fadeBackground = keyframes` @@ -13,6 +12,7 @@ type WrapperType = { reverseAnimation?: boolean; direction: ModalDirection; }; + export const Wrapper = styled.div` position: fixed; top: 0; @@ -28,7 +28,7 @@ export const Wrapper = styled.div` z-index: 99998; - animation: ${fadeBackground} 0.5s linear; + animation: ${fadeBackground} 0.3s linear; animation-fill-mode: forwards; opacity: ${({ reverseAnimation }) => (reverseAnimation ? 0 : 1)}; @@ -93,24 +93,21 @@ type ModalWrapperType = { const minimumMargin = 32; export const ModalContentWrapper = styled.div` - --padding-modal-content: ${({ padding }) => - padding === "normal" ? "24px" : "16px"}; + --padding-base: ${({ padding }) => (padding === "normal" ? "24px" : "16px")}; + --padding-modal-content: calc(var(--padding-base) / 1.5); max-height: ${({ height, topYOffset }) => height ? `min(calc(100svh - ${minimumMargin * 2}px - ${topYOffset ?? 0}px), ${height}px)` : "calc(100svh - 64px)"}; max-width: ${({ width }) => width ?? 800}px; - - height: fit-content; width: calc(100% - 32px); display: flex; flex-direction: column; align-items: flex-start; - gap: var(--padding-modal-content); margin: 0 auto; - padding: var(--padding-modal-content); + padding: 0; margin-top: ${({ topYOffset }) => topYOffset ?? 0}px; margin-bottom: ${({ bottomYOffset }) => bottomYOffset ?? 0}px; @@ -122,6 +119,11 @@ export const ModalContentWrapper = styled.div` position: relative; overflow: hidden; + + ${QUERIES.tabletAndUp} { + --padding-modal-content: var(--padding-base); + border-radius: 24px; + } `; export const TitleAndExitWrapper = styled.div` @@ -132,7 +134,7 @@ export const TitleAndExitWrapper = styled.div` align-items: center; gap: 12px; - padding: 0px; + padding-bottom: var(--padding-modal-content); width: 100%; `; @@ -148,10 +150,6 @@ export const Title = styled.p` } `; -export const StyledExitIcon = styled(CrossIcon)` - cursor: pointer; -`; - export const ElementRowDivider = styled.div` height: 1px; min-height: 1px; @@ -160,3 +158,51 @@ export const ElementRowDivider = styled.div` margin-left: calc(0px - var(--padding-modal-content)); width: calc(100% + (2 * var(--padding-modal-content))); `; + +export const CloseButton = styled.button` + border: none; + background-color: transparent; + display: inline-flex; + outline: none; + padding: 4px; + border-radius: 4px; + cursor: pointer; + + &:hover, + &:focus-visible { + background-color: ${COLORS["grey-400-15"]}; + } + + &:focus-visible { + outline: 2px solid ${COLORS.aqua}; + } +`; + +export const ModalHeader = styled.div` + position: sticky; + top: 0; + z-index: 10; + background: #202024; + padding: var(--padding-modal-content); + padding-bottom: 0; + flex-shrink: 0; + width: 100%; +`; + +export const ModalContent = styled.div<{ noScroll?: boolean }>` + flex: 1; + overflow: ${({ noScroll }) => (noScroll ? "clip" : "hidden scroll")}; + padding: var(--padding-modal-content); + min-height: 0; + width: 100%; +`; + +export const ModalFooter = styled.div` + position: sticky; + bottom: 0; + z-index: 10; + background: #202024; + padding: var(--padding-modal-content); + padding-top: 0; + flex-shrink: 0; +`; diff --git a/src/components/Modal/Modal.tsx b/src/components/Modal/Modal.tsx index 5639631e0..917b4a9a4 100644 --- a/src/components/Modal/Modal.tsx +++ b/src/components/Modal/Modal.tsx @@ -1,14 +1,19 @@ import usePageScrollLock from "hooks/usePageScrollLock"; +import { useTabIndexManager } from "hooks/useTabIndexManager"; import React, { useEffect, useRef, useState, useLayoutEffect } from "react"; import { createPortal } from "react-dom"; import { + CloseButton, ElementRowDivider, ModalContentWrapper, - StyledExitIcon, + ModalHeader, + ModalContent, + ModalFooter, Title, TitleAndExitWrapper, Wrapper, } from "./Modal.styles"; +import { ReactComponent as ExitIcon } from "assets/icons/cross.svg"; type ModalDirectionOrientation = "middle" | "top" | "bottom"; export type ModalDirection = { @@ -34,9 +39,12 @@ export type ModalProps = { topYOffset?: number; "data-cy"?: string; bottomYOffset?: number; - + noScroll?: boolean; children?: React.ReactNode; + footer?: React.ReactNode; titleBorder?: boolean; + className?: string; + closeButtonTabIndex?: number; }; const Modal = ({ @@ -48,12 +56,16 @@ const Modal = ({ exitModalHandler: externalModalExitHandler, disableExitOverride, children, + footer, verticalLocation: _verticalLocation, topYOffset, bottomYOffset, padding, + className, "data-cy": dataCy, titleBorder = false, + noScroll = false, + closeButtonTabIndex = 999999, // should default to being last }: ModalProps) => { const verticalLocation: ModalDirection | undefined = typeof _verticalLocation === "string" @@ -77,6 +89,9 @@ const Modal = ({ const [forwardAnimation, setForwardAnimation] = useState(true); const { lockScroll, unlockScroll } = usePageScrollLock(); + // Manage tab indices when modal is open - only elements inside modal will be focusable + useTabIndexManager(!!isOpen, modalContentRef); + const offModalClickHandler = (event: React.MouseEvent) => { if ( modalContentRef.current && @@ -145,18 +160,29 @@ const Modal = ({ topYOffset={topYOffset} bottomYOffset={bottomYOffset} padding={padding ?? "normal"} + className={className} > - - {typeof title === "string" ? ( - {title} - ) : ( -
{title}
- )} - - externalModalExitHandler()} /> -
- {titleBorder && } - {children} + + + {typeof title === "string" ? ( + {title} + ) : ( +
{title}
+ )} + + externalModalExitHandler()} + > + + +
+ {titleBorder && } +
+ + {children} + + {footer && {footer}} , container.current diff --git a/src/components/Sidebar/components/NavigationContent.tsx b/src/components/Sidebar/components/NavigationContent.tsx index a39d13000..ece53394f 100644 --- a/src/components/Sidebar/components/NavigationContent.tsx +++ b/src/components/Sidebar/components/NavigationContent.tsx @@ -5,27 +5,20 @@ import { useSidebarContext } from "hooks/useSidebarContext"; import { AccountContent } from "./AccountContent"; import { SidebarItem } from "./SidebarItem"; import { TermsOfServiceDisclaimer } from "./TermsOfServiceDisclaimer"; +import { NAVIGATION_LINKS } from "Routes"; -const sidebarNavigationLinks = [ - { - pathName: "/bridge", - title: "Bridge", - }, - { - pathName: "/pool", - title: "Pool", - }, - { - pathName: "/rewards", - title: "Rewards", - }, - { - pathName: "/transactions", - title: "Transactions", - }, +type NavigationLInk = { + href: string; + name: string; + isExternalLink?: boolean; + rightIcon?: React.ReactNode; +}; + +const sidebarNavigationLinks: NavigationLInk[] = [ + ...NAVIGATION_LINKS, { - pathName: "https://docs.across.to/", - title: "Docs", + href: "https://docs.across.to/", + name: "Docs", isExternalLink: true, rightIcon: , }, @@ -75,20 +68,20 @@ export function NavigationContent() { <> {sidebarNavigationLinks.map((item) => - item.isExternalLink ? ( + item?.isExternalLink ? ( ) : ( ) )} diff --git a/src/components/TokenImage/TokenImage.tsx b/src/components/TokenImage/TokenImage.tsx new file mode 100644 index 000000000..a93ced743 --- /dev/null +++ b/src/components/TokenImage/TokenImage.tsx @@ -0,0 +1,31 @@ +import { useState, useEffect, ImgHTMLAttributes } from "react"; +import fallbackLogo from "assets/token-logos/fallback.svg"; + +type TokenImageProps = ImgHTMLAttributes & { + src?: string; + alt: string; +}; + +/** + * TokenImage component that handles missing or broken token logo URLs + * Falls back to a default logo if the URL is missing or the image fails to load + */ +export function TokenImage({ src, alt, ...props }: TokenImageProps) { + const [imageError, setImageError] = useState(false); + + // Reset error state when src changes + useEffect(() => { + setImageError(false); + }, [src]); + + const imageSrc = !src || imageError ? fallbackLogo : src; + + return ( + {alt} setImageError(true)} + /> + ); +} diff --git a/src/components/TokenImage/index.ts b/src/components/TokenImage/index.ts new file mode 100644 index 000000000..85c1399a8 --- /dev/null +++ b/src/components/TokenImage/index.ts @@ -0,0 +1 @@ +export * from "./TokenImage"; diff --git a/src/components/Tooltip/Tooltip.styles.tsx b/src/components/Tooltip/Tooltip.styles.tsx index 0e3476674..7face2c94 100644 --- a/src/components/Tooltip/Tooltip.styles.tsx +++ b/src/components/Tooltip/Tooltip.styles.tsx @@ -3,7 +3,8 @@ import { Tooltip } from "react-tooltip"; import { ReactComponent as RoundedCheckmark16 } from "assets/icons/checkmark-circle.svg"; export const StyledAnchor = styled.a<{ width?: string }>` - line-height: 1; + line-height: 1em; + height: 1em; width: ${({ width }) => width}; `; diff --git a/src/components/index.ts b/src/components/index.ts index 9d8d74ed6..3d90df9f8 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -16,3 +16,4 @@ export * from "./Button"; export * from "./Badge"; export * from "./ExternalLink"; export * from "./ErrorBoundary"; +export * from "./TokenImage"; diff --git a/src/constants/tokens.ts b/src/constants/tokens.ts index 860e0d939..731f5de32 100644 --- a/src/constants/tokens.ts +++ b/src/constants/tokens.ts @@ -23,6 +23,8 @@ import unknownLogo from "assets/icons/question-circle.svg"; import cakeLogo from "assets/token-logos/cake.svg"; import bnbLogo from "assets/token-logos/bnb.svg"; import vlrLogo from "assets/token-logos/vlr.svg"; +import hypeLogo from "assets/token-logos/hype.svg"; +import solLogo from "assets/token-logos/sol.svg"; import { BRIDGED_USDC_SYMBOLS } from "../utils/sdk"; @@ -39,6 +41,8 @@ export type TokenInfo = { addresses?: Record; // optional, if this is a stable coin isStable?: boolean; + // optional price in USD from swap tokens API + priceUsd?: string | null; }; export type TokenInfoList = TokenInfo[]; @@ -114,4 +118,6 @@ export const orderedTokenLogos = { BNB: bnbLogo, WBNB: bnbLogo, VLR: vlrLogo, + HYPE: hypeLogo, + SOL: solLogo, } as const satisfies Partial>; diff --git a/src/data/swap-tokens.json b/src/data/swap-tokens.json new file mode 100644 index 000000000..ee7b21ea8 --- /dev/null +++ b/src/data/swap-tokens.json @@ -0,0 +1,10968 @@ +{ + "tokens": [ + { + "chainId": 1, + "address": "0x111111111117dC0aa78b770fA6A738034120C302", + "name": "1inch", + "symbol": "1INCH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028", + "priceUsd": "0.161675" + }, + { + "chainId": 1, + "address": "0x3E5A19c91266aD8cE2477B91585d1856B84062dF", + "name": "Ancient8", + "symbol": "A8", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/39170/standard/A8_Token-04_200x200.png?1720798300", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9", + "name": "Aave", + "symbol": "AAVE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110", + "priceUsd": "218.02" + }, + { + "chainId": 1, + "address": "0xB98d4C97425d9908E66E53A6fDf673ACcA0BE986", + "name": "Arcblock", + "symbol": "ABT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2341/thumb/arcblock.png?1547036543", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0xEd04915c23f00A313a544955524EB7DBD823143d", + "name": "Alchemy Pay", + "symbol": "ACH", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/12390/thumb/ACH_%281%29.png?1599691266", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x44108f0223A3C3028F5Fe7AEC7f9bb2E66beF82F", + "name": "Across Protocol Token", + "symbol": "ACX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/28161/large/across-200x200.png?1696527165", + "priceUsd": "0.065257" + }, + { + "chainId": 1, + "address": "0xADE00C28244d5CE17D72E40330B1c318cD12B7c3", + "name": "Ambire AdEx", + "symbol": "ADX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/847/thumb/Ambire_AdEx_Symbol_color.png?1655432540", + "priceUsd": "0.12913613945549834" + }, + { + "chainId": 1, + "address": "0x91Af0fBB28ABA7E31403Cb457106Ce79397FD4E6", + "name": "Aergo", + "symbol": "AERGO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4490/thumb/aergo.png?1647696770", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0xB528edBef013aff855ac3c50b381f253aF13b997", + "name": "Aevo", + "symbol": "AEVO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/35893/standard/aevo.png", + "priceUsd": "0.05699" + }, + { + "chainId": 1, + "address": "0x1a7e4e63778B4f12a199C062f3eFdD288afCBce8", + "name": "agEur", + "symbol": "agEUR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19479/standard/agEUR.png?1696518915", + "priceUsd": "1.15" + }, + { + "chainId": 1, + "address": "0x32353A6C91143bfd6C7d363B546e62a9A2489A20", + "name": "Adventure Gold", + "symbol": "AGLD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/18125/thumb/lpgblc4h_400x400.jpg?1630570955", + "priceUsd": "0.5737477135444219" + }, + { + "chainId": 1, + "address": "0x626E8036dEB333b408Be468F951bdB42433cBF18", + "name": "AIOZ Network", + "symbol": "AIOZ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14631/thumb/aioz_logo.png?1617413126", + "priceUsd": "0.178339" + }, + { + "chainId": 1, + "address": "0xdBdb4d16EdA451D0503b854CF79D55697F90c8DF", + "name": "Alchemix", + "symbol": "ALCX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14113/thumb/Alchemix.png?1614409874", + "priceUsd": "7" + }, + { + "chainId": 1, + "address": "0x27702a26126e0B3702af63Ee09aC4d1A084EF628", + "name": "Aleph im", + "symbol": "ALEPH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11676/thumb/Monochram-aleph.png?1608483725", + "priceUsd": "0.06160677777293554" + }, + { + "chainId": 1, + "address": "0x6B0b3a982b4634aC68dD83a4DBF02311cE324181", + "name": "Alethea Artificial Liquid Intelligence", + "symbol": "ALI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/22062/thumb/alethea-logo-transparent-colored.png?1642748848", + "priceUsd": "0.003796547395447448" + }, + { + "chainId": 1, + "address": "0xAC51066d7bEC65Dc4589368da368b212745d63E8", + "name": "My Neighbor Alice", + "symbol": "ALICE", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/14375/thumb/alice_logo.jpg?1615782968", + "priceUsd": "0.2783198093386334" + }, + { + "chainId": 1, + "address": "0xa1faa113cbE53436Df28FF0aEe54275c13B40975", + "name": "Alpha Venture DAO", + "symbol": "ALPHA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12738/thumb/AlphaToken_256x256.png?1617160876", + "priceUsd": "0.00924366616699257" + }, + { + "chainId": 1, + "address": "0x8457CA5040ad67fdebbCC8EdCE889A335Bc0fbFB", + "name": "AltLayer", + "symbol": "ALT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/34608/standard/Logomark_200x200.png", + "priceUsd": "0.01672718" + }, + { + "chainId": 1, + "address": "0xfF20817765cB7f73d4bde2e66e067E58D11095C2", + "name": "Amp", + "symbol": "AMP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12409/thumb/amp-200x200.png?1599625397", + "priceUsd": "0.00248075" + }, + { + "chainId": 1, + "address": "0x8290333ceF9e6D528dD5618Fb97a76f268f3EDD4", + "name": "Ankr", + "symbol": "ANKR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4324/thumb/U85xTl2.png?1608111978", + "priceUsd": "0.009899872077344824" + }, + { + "chainId": 1, + "address": "0xa117000000f279D81A1D3cc75430fAA017FA5A2e", + "name": "Aragon", + "symbol": "ANT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/681/thumb/JelZ58cv_400x400.png?1601449653", + "priceUsd": "0.44181535090054025" + }, + { + "chainId": 1, + "address": "0x4d224452801ACEd8B2F0aebE155379bb5D594381", + "name": "ApeCoin", + "symbol": "APE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24383/small/apecoin.jpg?1647476455", + "priceUsd": "0.39828281981361624" + }, + { + "chainId": 1, + "address": "0x0b38210ea11411557c13457D4dA7dC6ea731B88a", + "name": "API3", + "symbol": "API3", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13256/thumb/api3.jpg?1606751424", + "priceUsd": "0.676605" + }, + { + "chainId": 1, + "address": "0x594DaaD7D77592a2b97b725A7AD59D7E188b5bFa", + "name": "Apu Apustaja", + "symbol": "APU", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/35986/large/200x200.png?1710308147", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0xB50721BCf8d664c30412Cfbc6cf7a15145234ad1", + "name": "Arbitrum", + "symbol": "ARB", + "decimals": 18, + "logoUrl": "https://arbitrum.foundation/logo.png", + "priceUsd": "0.295531" + }, + { + "chainId": 1, + "address": "0x6E2a43be0B1d33b726f0CA3b8de60b3482b8b050", + "name": "Arkham", + "symbol": "ARKM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/30929/standard/Arkham_Logo_CG.png?1696529771", + "priceUsd": "0.28418993701889206" + }, + { + "chainId": 1, + "address": "0xBA50933C268F567BDC86E1aC131BE072C6B0b71a", + "name": "ARPA Chain", + "symbol": "ARPA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/8506/thumb/9u0a23XY_400x400.jpg?1559027357", + "priceUsd": "0.012067582983950165" + }, + { + "chainId": 1, + "address": "0x64D91f12Ece7362F91A6f8E7940Cd55F05060b92", + "name": "ASH", + "symbol": "ASH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15714/thumb/omnPqaTY.png?1622820503", + "priceUsd": "0.8508562485544615" + }, + { + "chainId": 1, + "address": "0x2565ae0385659badCada1031DB704442E1b69982", + "name": "Assemble Protocol", + "symbol": "ASM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11605/thumb/gpvrlkSq_400x400_%281%29.jpg?1591775789", + "priceUsd": "0.057178514136898846" + }, + { + "chainId": 1, + "address": "0x27054b13b1B798B345b591a4d22e6562d47eA75a", + "name": "AirSwap", + "symbol": "AST", + "decimals": 4, + "logoUrl": "https://assets.coingecko.com/coins/images/1019/thumb/Airswap.png?1630903484", + "priceUsd": "0.024542771701041664" + }, + { + "chainId": 1, + "address": "0xA2120b9e674d3fC3875f415A7DF52e382F141225", + "name": "Automata", + "symbol": "ATA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15985/thumb/ATA.jpg?1622535745", + "priceUsd": "0.027353361382434063" + }, + { + "chainId": 1, + "address": "0xbe0Ed4138121EcFC5c0E56B40517da27E6c5226B", + "name": "Aethir Token", + "symbol": "ATH", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/36179/large/logogram_circle_dark_green_vb_green_(1).png?1718232706", + "priceUsd": "0.02683334" + }, + { + "chainId": 1, + "address": "0xA9B1Eb5908CfC3cdf91F9B8B3a74108598009096", + "name": "Bounce", + "symbol": "AUCTION", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13860/thumb/1_KtgpRIJzuwfHe0Rl0avP_g.jpeg?1612412025", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x18aAA7115705e8be94bfFEBDE57Af9BFc265B998", + "name": "Audius", + "symbol": "AUDIO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12913/thumb/AudiusCoinLogo_2x.png?1603425727", + "priceUsd": "0.03864841" + }, + { + "chainId": 1, + "address": "0x845576c64f9754CF09d87e45B720E82F3EeF522C", + "name": "Artverse Token", + "symbol": "AVT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19727/thumb/ewnektoB_400x400.png?1635767094", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x467719aD09025FcC6cF6F8311755809d45a5E5f3", + "name": "Axelar", + "symbol": "AXL", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/27277/large/V-65_xQ1_400x400.jpeg", + "priceUsd": "0.17062776472041447" + }, + { + "chainId": 1, + "address": "0xBB0E17EF65F82Ab018d8EDd776e8DD940327B28b", + "name": "Axie Infinity", + "symbol": "AXS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13029/thumb/axie_infinity_logo.png?1604471082", + "priceUsd": "1.44" + }, + { + "chainId": 1, + "address": "0x3472A5A71965499acd81997a54BBA8D852C6E53d", + "name": "Badger DAO", + "symbol": "BADGER", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13287/thumb/badger_dao_logo.jpg?1607054976", + "priceUsd": "0.787817" + }, + { + "chainId": 1, + "address": "0xba100000625a3754423978a60c9317c58a424e3D", + "name": "Balancer", + "symbol": "BAL", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xba100000625a3754423978a60c9317c58a424e3D/logo.png", + "priceUsd": "0.989933" + }, + { + "chainId": 1, + "address": "0xBA11D00c5f74255f56a5E366F4F77f5A186d7f55", + "name": "Band Protocol", + "symbol": "BAND", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9545/thumb/band-protocol.png?1568730326", + "priceUsd": "0.5038638407544159" + }, + { + "chainId": 1, + "address": "0x0D8775F648430679A709E98d2b0Cb6250d2887EF", + "name": "Basic Attention Token", + "symbol": "BAT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/677/thumb/basic-attention-token.png?1547034427", + "priceUsd": "0.160722" + }, + { + "chainId": 1, + "address": "0x62D0A8458eD7719FDAF978fe5929C6D342B0bFcE", + "name": "Beam", + "symbol": "BEAM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/32417/standard/chain-logo.png?1698114384", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0xF17e65822b568B3903685a7c9F496CF7656Cc6C2", + "name": "Biconomy", + "symbol": "BICO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/21061/thumb/biconomy_logo.jpg?1638269749", + "priceUsd": "0.05850511879605278" + }, + { + "chainId": 1, + "address": "0x64Bc2cA1Be492bE7185FAA2c8835d9b824c8a194", + "name": "Big Time", + "symbol": "BIGTIME", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/32251/standard/-6136155493475923781_121.jpg?1696998691", + "priceUsd": "0.03101977349966254" + }, + { + "chainId": 1, + "address": "0xcb1592591996765Ec0eFc1f92599A19767ee5ffA", + "name": "BIO", + "symbol": "BIO", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/53022/large/bio.jpg?1735011002", + "priceUsd": "0.08149" + }, + { + "chainId": 1, + "address": "0x1A4b46696b2bB4794Eb3D4c26f1c55F9170fa4C5", + "name": "BitDAO", + "symbol": "BIT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17627/thumb/rI_YptK8.png?1653983088", + "priceUsd": "1.4611940046816017" + }, + { + "chainId": 1, + "address": "0x72e4f9F808C49A2a61dE9C5896298920Dc4EEEa9", + "name": "HarryPotterObamaSonic10Inu", + "symbol": "BITCOIN", + "decimals": 8, + "logoUrl": "https://coin-images.coingecko.com/coins/images/30323/large/hpos10i_logo_casino_night-dexview.png?1696529224", + "priceUsd": "0.061266" + }, + { + "chainId": 1, + "address": "0x5283D291DBCF85356A21bA090E6db59121208b44", + "name": "Blur", + "symbol": "BLUR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/28453/large/blur.png?1670745921", + "priceUsd": "0.06344393927530152" + }, + { + "chainId": 1, + "address": "0x5732046A883704404F284Ce41FfADd5b007FD668", + "name": "Bluzelle", + "symbol": "BLZ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2848/thumb/ColorIcon_3x.png?1622516510", + "priceUsd": "0.024464254908994877" + }, + { + "chainId": 1, + "address": "0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C", + "name": "Bancor Network Token", + "symbol": "BNT", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C/logo.png", + "priceUsd": "0.57299" + }, + { + "chainId": 1, + "address": "0x42bBFa2e77757C645eeaAd1655E0911a7553Efbc", + "name": "Boba Network", + "symbol": "BOBA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/20285/thumb/BOBA.png?1636811576", + "priceUsd": "0.06298983696543212" + }, + { + "chainId": 1, + "address": "0x0391D2021f89DC339F60Fff84546EA23E337750f", + "name": "BarnBridge", + "symbol": "BOND", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12811/thumb/barnbridge.jpg?1602728853", + "priceUsd": "0.12442331500242615" + }, + { + "chainId": 1, + "address": "0x799ebfABE77a6E34311eeEe9825190B9ECe32824", + "name": "Braintrust", + "symbol": "BTRST", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/18100/thumb/braintrust.PNG?1630475394", + "priceUsd": "0.38686839775968385" + }, + { + "chainId": 1, + "address": "0x4Fabb145d64652a948d72533023f6E7A623C7C53", + "name": "Binance USD", + "symbol": "BUSD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766", + "priceUsd": "0.998509" + }, + { + "chainId": 1, + "address": "0xAE12C5930881c53715B369ceC7606B70d8EB229f", + "name": "Coin98", + "symbol": "C98", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17117/thumb/logo.png?1626412904", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x152649eA73beAb28c5b49B26eb48f7EAD6d4c898", + "name": "PancakeSwap", + "symbol": "CAKE", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/12632/large/pancakeswap-cake-logo_%281%29.png?1696512440", + "priceUsd": "2.41" + }, + { + "chainId": 1, + "address": "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf", + "name": "Coinbase Wrapped BTC", + "symbol": "cbBTC", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/40143/standard/cbbtc.webp", + "priceUsd": "109583" + }, + { + "chainId": 1, + "address": "0xBe9895146f7AF43049ca1c1AE358B0541Ea49704", + "name": "Coinbase Wrapped Staked ETH", + "symbol": "cbETH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/27008/large/cbeth.png", + "priceUsd": "4228.87" + }, + { + "chainId": 1, + "address": "0x3294395e62F4eB6aF3f1Fcf89f5602D90Fb3Ef69", + "name": "Celo native asset (Wormhole)", + "symbol": "CELO", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/wormhole-foundation/wormhole-token-list/main/assets/celo_wh.png", + "priceUsd": "0.279072646756324" + }, + { + "chainId": 1, + "address": "0x4F9254C83EB525f9FCf346490bbb3ed28a81C667", + "name": "Celer Network", + "symbol": "CELR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4379/thumb/Celr.png?1554705437", + "priceUsd": "0.005579833386524931" + }, + { + "chainId": 1, + "address": "0x8A2279d4A90B6fe1C4B30fa660cC9f926797bAA2", + "name": "Chromia", + "symbol": "CHR", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/5000/thumb/Chromia.png?1559038018", + "priceUsd": "0.07721099403724642" + }, + { + "chainId": 1, + "address": "0x3506424F91fD33084466F402d5D97f05F8e3b4AF", + "name": "Chiliz", + "symbol": "CHZ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/8834/thumb/Chiliz.png?1561970540", + "priceUsd": "0.030874660463733772" + }, + { + "chainId": 1, + "address": "0x80C62FE4487E1351b47Ba49809EBD60ED085bf52", + "name": "Clover Finance", + "symbol": "CLV", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15278/thumb/clover.png?1645084454", + "priceUsd": "0.01269938" + }, + { + "chainId": 1, + "address": "0xc00e94Cb662C3520282E6f5717214004A7f26888", + "name": "Compound", + "symbol": "COMP", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png", + "priceUsd": "34.86" + }, + { + "chainId": 1, + "address": "0x44f49ff0da2498bCb1D3Dc7C0f999578F67FD8C6", + "name": "Corn", + "symbol": "CORN", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/54471/large/corn.jpg?1739933588", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0xDDB3422497E61e13543BeA06989C0789117555c5", + "name": "COTI", + "symbol": "COTI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2962/thumb/Coti.png?1559653863", + "priceUsd": "0.03151940229430002" + }, + { + "chainId": 1, + "address": "0x3D658390460295FB963f54dC0899cfb1c30776Df", + "name": "Circuits of Value", + "symbol": "COVAL", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/588/thumb/coval-logo.png?1599493950", + "priceUsd": "0.00046359686666586053" + }, + { + "chainId": 1, + "address": "0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB", + "name": "CoW Protocol", + "symbol": "COW", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24384/large/CoW-token_logo.png?1719524382", + "priceUsd": "0.218524" + }, + { + "chainId": 1, + "address": "0x66761Fa41377003622aEE3c7675Fc7b5c1C2FaC5", + "name": "Clearpool", + "symbol": "CPOOL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19252/large/photo_2022-08-31_12.45.02.jpeg?1696518697", + "priceUsd": "0.070134" + }, + { + "chainId": 1, + "address": "0xD417144312DbF50465b1C641d016962017Ef6240", + "name": "Covalent", + "symbol": "CQT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14168/thumb/covalent-cqt.png?1624545218", + "priceUsd": "0.001147369127038052" + }, + { + "chainId": 1, + "address": "0xA0b73E1Ff0B80914AB6fe0444E65848C4C34450b", + "name": "Cronos", + "symbol": "CRO", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/7310/thumb/oCw2s3GI_400x400.jpeg?1645172042", + "priceUsd": "0.147738" + }, + { + "chainId": 1, + "address": "0x08389495D7456E1951ddF7c3a1314A4bfb646d8B", + "name": "Crypterium", + "symbol": "CRPT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1901/thumb/crypt.png?1547036205", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0xD533a949740bb3306d119CC777fa900bA034cd52", + "name": "Curve DAO Token", + "symbol": "CRV", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xD533a949740bb3306d119CC777fa900bA034cd52/logo.png", + "priceUsd": "0.488167" + }, + { + "chainId": 1, + "address": "0x491604c0FDF08347Dd1fa4Ee062a822A5DD06B5D", + "name": "Cartesi", + "symbol": "CTSI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021", + "priceUsd": "0.07262853845364987" + }, + { + "chainId": 1, + "address": "0x321C2fE4446C7c963dc41Dd58879AF648838f98D", + "name": "Cryptex Finance", + "symbol": "CTX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14932/thumb/glossy_icon_-_C200px.png?1619073171", + "priceUsd": "1.2297754796675755" + }, + { + "chainId": 1, + "address": "0xDf801468a808a32656D2eD2D2d80B72A129739f4", + "name": "Somnium Space CUBEs", + "symbol": "CUBE", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/10687/thumb/CUBE_icon.png?1617026861", + "priceUsd": "0.23698677096161377" + }, + { + "chainId": 1, + "address": "0x41e5560054824eA6B0732E656E3Ad64E20e94E45", + "name": "Civic", + "symbol": "CVC", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/788/thumb/civic.png?1547034556", + "priceUsd": "0.0538688129724869" + }, + { + "chainId": 1, + "address": "0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B", + "name": "Convex Finance", + "symbol": "CVX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15585/thumb/convex.png?1621256328", + "priceUsd": "2.24" + }, + { + "chainId": 1, + "address": "0x7ABc8A5768E6bE61A6c693a6e4EAcb5B60602C4D", + "name": "Covalent X Token", + "symbol": "CXT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/39177/large/CXT_Ticker.png?1720829918", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x6B175474E89094C44Da98b954EedeAC495271d0F", + "name": "Dai Stablecoin", + "symbol": "DAI", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png", + "priceUsd": "0.999421" + }, + { + "chainId": 1, + "address": "0x081131434f93063751813C619Ecca9C4dC7862a3", + "name": "Mines of Dalarnia", + "symbol": "DAR", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/19837/thumb/dar.png?1636014223", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x3A880652F47bFaa771908C07Dd8673A787dAEd3A", + "name": "DerivaDAO", + "symbol": "DDX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13453/thumb/ddx_logo.png?1608741641", + "priceUsd": "0.04109032433994934" + }, + { + "chainId": 1, + "address": "0x3597bfD533a99c9aa083587B074434E61Eb0A258", + "name": "Dent", + "symbol": "DENT", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/1152/thumb/gLCEA2G.png?1604543239", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0xfB7B4564402E5500dB5bB6d63Ae671302777C75a", + "name": "DexTools", + "symbol": "DEXT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11603/thumb/dext.png?1605790188", + "priceUsd": "0.316372" + }, + { + "chainId": 1, + "address": "0x84cA8bc7997272c7CfB4D0Cd3D55cd942B3c9419", + "name": "DIA", + "symbol": "DIA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11955/thumb/image.png?1646041751", + "priceUsd": "0.519988" + }, + { + "chainId": 1, + "address": "0x0AbdAce70D3790235af448C88547603b945604ea", + "name": "district0x", + "symbol": "DNT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/849/thumb/district0x.png?1547223762", + "priceUsd": "0.019498454296220578" + }, + { + "chainId": 1, + "address": "0x1494CA1F11D487c2bBe4543E90080AeBa4BA3C2b", + "name": "DeFi Pulse Index", + "symbol": "DPI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12465/thumb/defi_pulse_index_set.png?1600051053", + "priceUsd": "78.87" + }, + { + "chainId": 1, + "address": "0x3Ab6Ed69Ef663bd986Ee59205CCaD8A20F98b4c2", + "name": "Drep", + "symbol": "DREP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14578/thumb/KotgsCgS_400x400.jpg?1617094445", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0xB1D1eae60EEA9525032a6DCb4c1CE336a1dE71BE", + "name": "Derive", + "symbol": "DRV", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/52889/large/Token_Logo.png?1734601695", + "priceUsd": "0.04755087585025541" + }, + { + "chainId": 1, + "address": "0x92D6C1e31e14520e676a687F0a93788B716BEff5", + "name": "dYdX", + "symbol": "DYDX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17500/thumb/hjnIm9bV.jpg?1628009360", + "priceUsd": "0.04300396998006144" + }, + { + "chainId": 1, + "address": "0x961C8c0B1aaD0c0b10a51FeF6a867E3091BCef17", + "name": "DeFi Yield Protocol", + "symbol": "DYP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13480/thumb/DYP_Logo_Symbol-8.png?1655809066", + "priceUsd": "0.004508396120758961" + }, + { + "chainId": 1, + "address": "0xec53bF9167f50cDEB3Ae105f56099aaaB9061F83", + "name": "EigenLayer", + "symbol": "EIGEN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/37441/large/eigen.jpg?1728023974", + "priceUsd": "0.929322" + }, + { + "chainId": 1, + "address": "0xe6fd75ff38Adca4B97FBCD938c86b98772431867", + "name": "Elastos", + "symbol": "ELA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2780/thumb/Elastos.png?1597048112", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x761D38e5ddf6ccf6Cf7c55759d5210750B5D60F3", + "name": "Dogelon Mars", + "symbol": "ELON", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14962/thumb/6GxcPRo3_400x400.jpg?1619157413", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x57e114B691Db790C35207b2e685D4A43181e6061", + "name": "Ethena", + "symbol": "ENA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/36530/standard/ethena.png", + "priceUsd": "0.397316" + }, + { + "chainId": 1, + "address": "0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c", + "name": "Enjin Coin", + "symbol": "ENJ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1102/thumb/enjin-coin-logo.png?1547035078", + "priceUsd": "0.055772742990189285" + }, + { + "chainId": 1, + "address": "0xC18360217D8F7Ab5e7c516566761Ea12Ce7F9D72", + "name": "Ethereum Name Service", + "symbol": "ENS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19785/thumb/acatxTm8_400x400.jpg?1635850140", + "priceUsd": "14.7" + }, + { + "chainId": 1, + "address": "0xE2AD0BF751834f2fbdC62A41014f84d67cA1de2A", + "name": "Caldera", + "symbol": "ERA", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/54475/large/Token_Logo.png?1749676251", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0xBBc2AE13b23d715c30720F079fcd9B4a74093505", + "name": "Ethernity Chain", + "symbol": "ERN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14238/thumb/LOGO_HIGH_QUALITY.png?1647831402", + "priceUsd": "0.06511723445815479" + }, + { + "chainId": 1, + "address": "0xFe0c30065B384F05761f15d0CC899D4F9F9Cc0eB", + "name": "Ether.fi", + "symbol": "ETHFI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/35958/standard/etherfi.jpeg", + "priceUsd": "0.941531" + }, + { + "chainId": 1, + "address": "0xd9Fcd98c322942075A5C3860693e9f4f03AAE07b", + "name": "Euler", + "symbol": "EUL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/26149/thumb/YCvKDfl8_400x400.jpeg?1656041509", + "priceUsd": "8.59" + }, + { + "chainId": 1, + "address": "0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c", + "name": "Euro Coin", + "symbol": "EURC", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/26045/thumb/euro-coin.png?1655394420", + "priceUsd": "1.15" + }, + { + "chainId": 1, + "address": "0x888883b5F5D21fb10Dfeb70e8f9722B9FB0E5E51", + "name": "Schuman EUR P", + "symbol": "EUROP", + "decimals": 6, + "logoUrl": "https://coin-images.coingecko.com/coins/images/52132/large/europ-symbol-rgb.jpg?1732634862", + "priceUsd": "1.16" + }, + { + "chainId": 1, + "address": "0x8dF723295214Ea6f21026eeEb4382d475f146F9f", + "name": "Quantoz EURQ", + "symbol": "EURQ", + "decimals": 6, + "logoUrl": "https://coin-images.coingecko.com/coins/images/51853/large/EURQ_1000px_Color.png?1732071269", + "priceUsd": "1.15" + }, + { + "chainId": 1, + "address": "0x50753CfAf86c094925Bf976f218D043f8791e408", + "name": "StablR Euro", + "symbol": "EURR", + "decimals": 6, + "logoUrl": "https://coin-images.coingecko.com/coins/images/53720/large/stablreuro-logo.png?1737125898", + "priceUsd": "1.15" + }, + { + "chainId": 1, + "address": "0xa0246c9032bC3A600820415aE600c6388619A14D", + "name": "Harvest Finance", + "symbol": "FARM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12304/thumb/Harvest.png?1613016180", + "priceUsd": "21.50829936292606" + }, + { + "chainId": 1, + "address": "0xaea46A60368A7bD060eec7DF8CBa43b7EF41Ad85", + "name": "Fetch ai", + "symbol": "FET", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/5681/thumb/Fetch.jpg?1572098136", + "priceUsd": "0.240416" + }, + { + "chainId": 1, + "address": "0xef3A930e1FfFFAcd2fc13434aC81bD278B0ecC8d", + "name": "Stafi", + "symbol": "FIS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12423/thumb/stafi_logo.jpg?1599730991", + "priceUsd": "0.06782998323602395" + }, + { + "chainId": 1, + "address": "0xcf0C122c6b73ff809C693DB761e7BaeBe62b6a2E", + "name": "FLOKI", + "symbol": "FLOKI", + "decimals": 9, + "logoUrl": "https://assets.coingecko.com/coins/images/16746/standard/PNG_image.png?1696516318", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x720CD16b011b987Da3518fbf38c3071d4F0D1495", + "name": "Flux", + "symbol": "FLUX", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x720CD16b011b987Da3518fbf38c3071d4F0D1495/logo.png", + "priceUsd": "0.11215833814284282" + }, + { + "chainId": 1, + "address": "0x41545f8b9472D758bB669ed8EaEEEcD7a9C4Ec29", + "name": "Forta", + "symbol": "FORT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/25060/thumb/Forta_lgo_%281%29.png?1655353696", + "priceUsd": "0.03511001" + }, + { + "chainId": 1, + "address": "0x77FbA179C79De5B7653F68b5039Af940AdA60ce0", + "name": "Ampleforth Governance Token", + "symbol": "FORTH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14917/thumb/photo_2021-04-22_00.00.03.jpeg?1619020835", + "priceUsd": "2.27" + }, + { + "chainId": 1, + "address": "0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d", + "name": "ShapeShift FOX Token", + "symbol": "FOX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9988/thumb/FOX.png?1574330622", + "priceUsd": "0.01960978" + }, + { + "chainId": 1, + "address": "0x853d955aCEf822Db058eb8505911ED77F175b99e", + "name": "Frax", + "symbol": "FRAX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13422/thumb/frax_logo.png?1608476506", + "priceUsd": "0.995226" + }, + { + "chainId": 1, + "address": "0x4E15361FD6b4BB609Fa63C81A2be19d873717870", + "name": "Fantom", + "symbol": "FTM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4001/thumb/Fantom.png?1558015016", + "priceUsd": "0.14105110034270799" + }, + { + "chainId": 1, + "address": "0x8c15Ef5b4B21951d50E53E4fbdA8298FFAD25057", + "name": "Function X", + "symbol": "FX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/8186/thumb/47271330_590071468072434_707260356350705664_n.jpg?1556096683", + "priceUsd": "0.071802" + }, + { + "chainId": 1, + "address": "0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0", + "name": "Frax Share", + "symbol": "FXS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13423/thumb/frax_share.png?1608478989", + "priceUsd": "1.3" + }, + { + "chainId": 1, + "address": "0x9C7BEBa8F6eF6643aBd725e45a4E8387eF260649", + "name": "Gravity", + "symbol": "G", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/39200/large/gravity.jpg?1721020647", + "priceUsd": "0.00686152" + }, + { + "chainId": 1, + "address": "0x5fAa989Af96Af85384b8a938c2EdE4A7378D9875", + "name": "Galxe", + "symbol": "GAL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24530/thumb/GAL-Token-Icon.png?1651483533", + "priceUsd": "0.3828353287767888" + }, + { + "chainId": 1, + "address": "0xd1d2Eb1B1e90B638588728b4130137D262C87cae", + "name": "GALA", + "symbol": "GALA", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/12493/standard/GALA-COINGECKO.png?1696512310", + "priceUsd": "0.01004061" + }, + { + "chainId": 1, + "address": "0xdab396cCF3d84Cf2D07C4454e10C8A6F5b008D2b", + "name": "Goldfinch", + "symbol": "GFI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19081/thumb/GOLDFINCH.png?1634369662", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x3F382DbD960E3a9bbCeaE22651E88158d2791550", + "name": "Aavegotchi", + "symbol": "GHST", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12467/thumb/ghst_200.png?1600750321", + "priceUsd": "0.2979754318644054" + }, + { + "chainId": 1, + "address": "0x7DD9c5Cba05E151C895FDe1CF355C9A1D5DA6429", + "name": "Golem", + "symbol": "GLM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/542/thumb/Golem_Submark_Positive_RGB.png?1606392013", + "priceUsd": "0.18744152696222638" + }, + { + "chainId": 1, + "address": "0x6810e776880C02933D47DB1b9fc05908e5386b96", + "name": "Gnosis Token", + "symbol": "GNO", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6810e776880C02933D47DB1b9fc05908e5386b96/logo.png", + "priceUsd": "129.22" + }, + { + "chainId": 1, + "address": "0xccC8cb5229B0ac8069C51fd58367Fd1e622aFD97", + "name": "Gods Unchained", + "symbol": "GODS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17139/thumb/10631.png?1635718182", + "priceUsd": "0.0851611012010397" + }, + { + "chainId": 1, + "address": "0xc944E90C64B2c07662A292be6244BDf05Cda44a7", + "name": "The Graph", + "symbol": "GRT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13397/thumb/Graph_Token.png?1608145566", + "priceUsd": "0.061879" + }, + { + "chainId": 1, + "address": "0xDe30da39c46104798bB5aA3fe8B9e0e1F348163F", + "name": "Gitcoin", + "symbol": "GTC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15810/thumb/gitcoin.png?1621992929", + "priceUsd": "0.18092619482604927" + }, + { + "chainId": 1, + "address": "0x056Fd409E1d7A124BD7017459dFEa2F387b6d5Cd", + "name": "Gemini Dollar", + "symbol": "GUSD", + "decimals": 2, + "logoUrl": "https://assets.coingecko.com/coins/images/5992/thumb/gemini-dollar-gusd.png?1536745278", + "priceUsd": "1.0023196848094729" + }, + { + "chainId": 1, + "address": "0xC08512927D12348F6620a698105e1BAac6EcD911", + "name": "GYEN", + "symbol": "GYEN", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/14191/thumb/icon_gyen_200_200.png?1614843343", + "priceUsd": "0.005637732440162934" + }, + { + "chainId": 1, + "address": "0xb3999F658C0391d94A37f7FF328F3feC942BcADC", + "name": "Hashflow", + "symbol": "HFT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/26136/large/hashflow-icon-cmc.png", + "priceUsd": "0.05957399787228277" + }, + { + "chainId": 1, + "address": "0x71Ab77b7dbB4fa7e017BC15090b2163221420282", + "name": "Highstreet", + "symbol": "HIGH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/18973/thumb/logosq200200Coingecko.png?1634090470", + "priceUsd": "0.28994357876609145" + }, + { + "chainId": 1, + "address": "0xF5581dFeFD8Fb0e4aeC526bE659CFaB1f8c781dA", + "name": "HOPR", + "symbol": "HOPR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14061/thumb/Shared_HOPR_logo_512px.png?1614073468", + "priceUsd": "0.06940614686369405" + }, + { + "chainId": 1, + "address": "0xB705268213D593B8FD88d3FDEFF93AFF5CbDcfAE", + "name": "IDEX", + "symbol": "IDEX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2565/thumb/logomark-purple-286x286.png?1638362736", + "priceUsd": "0.020453701242775665" + }, + { + "chainId": 1, + "address": "0x767FE9EDC9E0dF98E07454847909b5E959D7ca0E", + "name": "Illuvium", + "symbol": "ILV", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14468/large/ILV.JPG", + "priceUsd": "10.64" + }, + { + "chainId": 1, + "address": "0xF57e7e7C23978C3cAEC3C3548E3D615c346e79fF", + "name": "Immutable X", + "symbol": "IMX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17233/thumb/imx.png?1636691817", + "priceUsd": "0.484859" + }, + { + "chainId": 1, + "address": "0x0954906da0Bf32d5479e25f46056d22f08464cab", + "name": "Index Cooperative", + "symbol": "INDEX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12729/thumb/index.png?1634894321", + "priceUsd": "1.027" + }, + { + "chainId": 1, + "address": "0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30", + "name": "Injective", + "symbol": "INJ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12882/thumb/Secondary_Symbol.png?1628233237", + "priceUsd": "7.66" + }, + { + "chainId": 1, + "address": "0x41D5D79431A913C4aE7d69a668ecdfE5fF9DFB68", + "name": "Inverse Finance", + "symbol": "INV", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14205/thumb/inverse_finance.jpg?1614921871", + "priceUsd": "35.28" + }, + { + "chainId": 1, + "address": "0x6fB3e0A217407EFFf7Ca062D46c26E5d60a14d69", + "name": "IoTeX", + "symbol": "IOTX", + "decimals": 18, + "logoUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/2777.png", + "priceUsd": "0.01111115" + }, + { + "chainId": 1, + "address": "0x23894DC9da6c94ECb439911cAF7d337746575A72", + "name": "Geojam", + "symbol": "JAM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24648/thumb/ey40AzBN_400x400.jpg?1648507272", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x7420B4b9a0110cdC71fB720908340C03F9Bc03EC", + "name": "JasmyCoin", + "symbol": "JASMY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13876/thumb/JASMY200x200.jpg?1612473259", + "priceUsd": "0.00996759" + }, + { + "chainId": 1, + "address": "0x4B1E80cAC91e2216EEb63e29B957eB91Ae9C2Be8", + "name": "Jupiter", + "symbol": "JUP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/10351/thumb/logo512.png?1632480932", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC", + "name": "Keep Network", + "symbol": "KEEP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3373/thumb/IuNzUb5b_400x400.jpg?1589526336", + "priceUsd": "0.05901314665671685" + }, + { + "chainId": 1, + "address": "0x3f80B1c54Ae920Be41a77f8B902259D48cf24cCf", + "name": "KernelDAO", + "symbol": "KERNEL", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/54326/large/Kernel_token_logo_2x.png?1739827205", + "priceUsd": "0.13274350947226085" + }, + { + "chainId": 1, + "address": "0x4CC19356f2D37338b9802aa8E8fc58B0373296E7", + "name": "SelfKey", + "symbol": "KEY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2034/thumb/selfkey.png?1548608934", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0xdd974D5C2e2928deA5F71b9825b8b646686BD200", + "name": "Kyber Network Crystal", + "symbol": "KNC", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdd974D5C2e2928deA5F71b9825b8b646686BD200/logo.png", + "priceUsd": "0.2958085377731128" + }, + { + "chainId": 1, + "address": "0x1cEB5cB57C4D4E2b2433641b95Dd330A33185A44", + "name": "Keep3rV1", + "symbol": "KP3R", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12966/thumb/kp3r_logo.jpg?1607057458", + "priceUsd": "3.5008260057144747" + }, + { + "chainId": 1, + "address": "0x464eBE77c293E473B48cFe96dDCf88fcF7bFDAC0", + "name": "KRYLL", + "symbol": "KRL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2807/thumb/krl.png?1547036979", + "priceUsd": "0.25018593864671257" + }, + { + "chainId": 1, + "address": "0x96543ef8d2C75C26387c1a319ae69c0BEE6f3fe7", + "name": "Kujira", + "symbol": "KUJI", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/20685/standard/kuji-200x200.png", + "priceUsd": "0.10693" + }, + { + "chainId": 1, + "address": "0x88909D489678dD17aA6D9609F89B0419Bf78FD9a", + "name": "Layer3", + "symbol": "L3", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/37768/large/Square.png", + "priceUsd": "0.021631311731649505" + }, + { + "chainId": 1, + "address": "0x0fc2a55d5BD13033f1ee0cdd11f60F7eFe66f467", + "name": "Lagrange", + "symbol": "LA", + "decimals": 18, + "logoUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/36510.png", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x037A54AaB062628C9Bbae1FDB1583c195585fe41", + "name": "LCX", + "symbol": "LCX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9985/thumb/zRPSu_0o_400x400.jpg?1574327008", + "priceUsd": "0.105842" + }, + { + "chainId": 1, + "address": "0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32", + "name": "Lido DAO", + "symbol": "LDO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13573/thumb/Lido_DAO.png?1609873644", + "priceUsd": "0.864329" + }, + { + "chainId": 1, + "address": "0x514910771AF9Ca656af840dff83E8264EcF986CA", + "name": "ChainLink Token", + "symbol": "LINK", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png", + "priceUsd": "17.15" + }, + { + "chainId": 1, + "address": "0xb59490aB09A0f526Cc7305822aC65f2Ab12f9723", + "name": "Litentry", + "symbol": "LIT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13825/large/logo_200x200.png", + "priceUsd": "0.3550586717406005" + }, + { + "chainId": 1, + "address": "0x61E90A50137E1F645c9eF4a0d3A4f01477738406", + "name": "League of Kingdoms", + "symbol": "LOKA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/22572/thumb/loka_64pix.png?1642643271", + "priceUsd": "0.1276487975729612" + }, + { + "chainId": 1, + "address": "0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0", + "name": "Loom Network", + "symbol": "LOOM", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0/logo.png", + "priceUsd": "0.40928274157433364" + }, + { + "chainId": 1, + "address": "0x58b6A8A3302369DAEc383334672404Ee733aB239", + "name": "Livepeer", + "symbol": "LPT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/7137/thumb/logo-circle-green.png?1619593365", + "priceUsd": "4.6791457830428405" + }, + { + "chainId": 1, + "address": "0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D", + "name": "Liquity", + "symbol": "LQTY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14665/thumb/200-lqty-icon.png?1617631180", + "priceUsd": "0.583037" + }, + { + "chainId": 1, + "address": "0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD", + "name": "LoopringCoin V2", + "symbol": "LRC", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD/logo.png", + "priceUsd": "0.0658652279297814" + }, + { + "chainId": 1, + "address": "0xd0a6053f087E87a25dC60701ba6E663b1a548E85", + "name": "BLOCKLORDS", + "symbol": "LRDS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/34775/standard/LRDS_PNG.png", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x8c1BEd5b9a0928467c9B1341Da1D7BD5e10b6549", + "name": "Liquid Staked ETH", + "symbol": "LSETH", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/28848/large/LsETH-receipt-token-circle.png?1696527824", + "priceUsd": "4135.52" + }, + { + "chainId": 1, + "address": "0x6033F7f88332B8db6ad452B7C6D5bB643990aE3f", + "name": "Lisk", + "symbol": "LSK", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/385/large/Lisk_logo.png?1722338450", + "priceUsd": "0.20190859970895755" + }, + { + "chainId": 1, + "address": "0x5f98805A4E8be255a32880FDeC7F6728C6568bA0", + "name": "Liquity USD", + "symbol": "LUSD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14666/thumb/Group_3.png?1617631327", + "priceUsd": "0.9873030260399316" + }, + { + "chainId": 1, + "address": "0x0F5D2fB29fb7d3CFeE444a200298f468908cC942", + "name": "Decentraland", + "symbol": "MANA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/878/thumb/decentraland-mana.png?1550108745", + "priceUsd": "0.227137" + }, + { + "chainId": 1, + "address": "0x69af81e73A73B40adF4f3d4223Cd9b1ECE623074", + "name": "Mask Network", + "symbol": "MASK", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14051/thumb/Mask_Network.jpg?1614050316", + "priceUsd": "0.810721" + }, + { + "chainId": 1, + "address": "0x08d967bb0134F2d07f7cfb6E246680c53927DD30", + "name": "MATH", + "symbol": "MATH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11335/thumb/2020-05-19-token-200.png?1589940590", + "priceUsd": "0.06497813206772664" + }, + { + "chainId": 1, + "address": "0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0", + "name": "Polygon", + "symbol": "MATIC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912", + "priceUsd": "0.18761580179600876" + }, + { + "chainId": 1, + "address": "0x949D48EcA67b17269629c7194F4b727d4Ef9E5d6", + "name": "Merit Circle", + "symbol": "MC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19304/thumb/Db4XqML.png?1634972154", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0xfC98e825A2264D890F9a1e68ed50E1526abCcacD", + "name": "Moss Carbon Credit", + "symbol": "MCO2", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14414/thumb/ENtxnThA_400x400.jpg?1615948522", + "priceUsd": "0.18401111727557032" + }, + { + "chainId": 1, + "address": "0x814e0908b12A99FeCf5BC101bB5d0b8B5cDf7d26", + "name": "Measurable Data Token", + "symbol": "MDT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2441/thumb/mdt_logo.png?1569813574", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0xb131f4A55907B10d1F0A50d8ab8FA09EC342cd74", + "name": "Memecoin", + "symbol": "MEME", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/32528/large/memecoin_(2).png", + "priceUsd": "0.00152408" + }, + { + "chainId": 1, + "address": "0x9E32b13ce7f2E80A01932B42553652E053D6ed8e", + "name": "Metis", + "symbol": "METIS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15595/thumb/metis.jpeg?1660285312", + "priceUsd": "9" + }, + { + "chainId": 1, + "address": "0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3", + "name": "Magic Internet Money", + "symbol": "MIM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/16786/thumb/mimlogopng.png?1624979612", + "priceUsd": "1.0017575701915018" + }, + { + "chainId": 1, + "address": "0x09a3EcAFa817268f77BE1283176B946C4ff2E608", + "name": "Mirror Protocol", + "symbol": "MIR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13295/thumb/mirror_logo_transparent.png?1611554658", + "priceUsd": "0.009529318446927107" + }, + { + "chainId": 1, + "address": "0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2", + "name": "Maker", + "symbol": "MKR", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2/logo.png", + "priceUsd": "1347.1" + }, + { + "chainId": 1, + "address": "0xec67005c4E498Ec7f55E092bd1d35cbC47C91892", + "name": "Melon", + "symbol": "MLN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/605/thumb/melon.png?1547034295", + "priceUsd": "6.678054091605723" + }, + { + "chainId": 1, + "address": "0x3c3a81e81dc49A522A592e7622A7E711c06bf354", + "name": "Mantle", + "symbol": "MNT", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/30980/large/Mantle-Logo-mark.png?1739213200", + "priceUsd": "1.45" + }, + { + "chainId": 1, + "address": "0xaaeE1A9723aaDB7afA2810263653A34bA2C21C7a", + "name": "Mog Coin", + "symbol": "MOG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/31059/large/MOG_LOGO_200x200.png", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x275f5Ad03be0Fa221B4C6649B8AeE09a42D9412A", + "name": "Monavale", + "symbol": "MONA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13298/thumb/monavale_logo.jpg?1607232721", + "priceUsd": "63.67594263056097" + }, + { + "chainId": 1, + "address": "0x58D97B57BB95320F9a05dC918Aef65434969c2B2", + "name": "Morpho Token", + "symbol": "MORPHO", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/29837/large/Morpho-token-icon.png?1726771230", + "priceUsd": "1.99" + }, + { + "chainId": 1, + "address": "0x3073f7aAA4DB83f95e9FFf17424F71D4751a3073", + "name": "Movement", + "symbol": "MOVE", + "decimals": 8, + "logoUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/32452.png", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x33349B282065b0284d756F0577FB39c158F935e6", + "name": "Maple", + "symbol": "MPL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14097/thumb/photo_2021-05-03_14.20.41.jpeg?1620022863", + "priceUsd": "0.8852244413968865" + }, + { + "chainId": 1, + "address": "0xF433089366899D83a9f26A773D59ec7eCF30355e", + "name": "Metal", + "symbol": "MTL", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/763/thumb/Metal.png?1592195010", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x65Ef703f5594D2573eb71Aaf55BC0CB548492df4", + "name": "Multichain", + "symbol": "MULTI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/22087/thumb/1_Wyot-SDGZuxbjdkaOeT2-A.png?1640764238", + "priceUsd": "0.43746221199167196" + }, + { + "chainId": 1, + "address": "0xe2f2a5C287993345a840Db3B0845fbC70f5935a5", + "name": "mStable USD", + "symbol": "MUSD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11576/thumb/mStable_USD.png?1595591803", + "priceUsd": "1.006125819559185" + }, + { + "chainId": 1, + "address": "0xB6Ca7399B4F9CA56FC27cBfF44F4d2e4Eef1fc81", + "name": "Muse DAO", + "symbol": "MUSE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13230/thumb/muse_logo.png?1606460453", + "priceUsd": "8.42" + }, + { + "chainId": 1, + "address": "0xAE788F80F2756A86aa2F410C651F2aF83639B95b", + "name": "GensoKishi Metaverse", + "symbol": "MV", + "decimals": 18, + "logoUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/17704.png", + "priceUsd": "0.005437315335802879" + }, + { + "chainId": 1, + "address": "0x5Ca381bBfb58f0092df149bD3D243b08B9a8386e", + "name": "MXC", + "symbol": "MXC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4604/thumb/mxc.png?1655534336", + "priceUsd": "0.0013547921838743743" + }, + { + "chainId": 1, + "address": "0x9E46A38F5DaaBe8683E10793b06749EEF7D733d1", + "name": "PolySwarm", + "symbol": "NCT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2843/thumb/ImcYCVfX_400x400.jpg?1628519767", + "priceUsd": "0.019384911292917074" + }, + { + "chainId": 1, + "address": "0x812Ba41e071C7b7fA4EBcFB62dF5F45f6fA853Ee", + "name": "Neiro", + "symbol": "Neiro", + "decimals": 9, + "logoUrl": "https://coin-images.coingecko.com/coins/images/39488/large/neiro.jpg?1731449567", + "priceUsd": "0.00017776" + }, + { + "chainId": 1, + "address": "0xD0eC028a3D21533Fdd200838F39c85B03679285D", + "name": "Newton", + "symbol": "NEWT", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/66819/large/newton.jpg?1750642513", + "priceUsd": "0.136508" + }, + { + "chainId": 1, + "address": "0x5Cf04716BA20127F1E2297AdDCf4B5035000c9eb", + "name": "NKN", + "symbol": "NKN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3375/thumb/nkn.png?1548329212", + "priceUsd": "0.018412080661207256" + }, + { + "chainId": 1, + "address": "0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671", + "name": "Numeraire", + "symbol": "NMR", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671/logo.png", + "priceUsd": "11.74" + }, + { + "chainId": 1, + "address": "0x4fE83213D56308330EC302a8BD641f1d0113A4Cc", + "name": "NuCypher", + "symbol": "NU", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3318/thumb/photo1198982838879365035.jpg?1547037916", + "priceUsd": "0.04897478152510191" + }, + { + "chainId": 1, + "address": "0x967da4048cD07aB37855c090aAF366e4ce1b9F48", + "name": "Ocean Protocol", + "symbol": "OCEAN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3687/thumb/ocean-protocol-logo.jpg?1547038686", + "priceUsd": "0.296196" + }, + { + "chainId": 1, + "address": "0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26", + "name": "Origin Protocol", + "symbol": "OGN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3296/thumb/op.jpg?1547037878", + "priceUsd": "0.04534032" + }, + { + "chainId": 1, + "address": "0xd26114cd6EE289AccF82350c8d8487fedB8A0C07", + "name": "OMG Network", + "symbol": "OMG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/776/thumb/OMG_Network.jpg?1591167168", + "priceUsd": "0.11151859794038739" + }, + { + "chainId": 1, + "address": "0x36E66fbBce51e4cD5bd3C62B637Eb411b18949D4", + "name": "Omni Network", + "symbol": "OMNI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/36465/standard/Symbol-Color.png?1711511095", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0xfAbA6f8e4a5E8Ab82F62fe7C39859FA577269BE3", + "name": "Ondo Finance", + "symbol": "ONDO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/26580/standard/ONDO.png?1696525656", + "priceUsd": "0.690433" + }, + { + "chainId": 1, + "address": "0x6F59e0461Ae5E2799F1fB3847f05a63B16d0DbF8", + "name": "ORCA Alliance", + "symbol": "ORCA", + "decimals": 18, + "logoUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/5183.png", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x0258F474786DdFd37ABCE6df6BBb1Dd5dfC4434a", + "name": "Orion Protocol", + "symbol": "ORN", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/11841/thumb/orion_logo.png?1594943318", + "priceUsd": "0.1211616683135028" + }, + { + "chainId": 1, + "address": "0x4575f41308EC1483f3d399aa9a2826d74Da13Deb", + "name": "Orchid", + "symbol": "OXT", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x4575f41308EC1483f3d399aa9a2826d74Da13Deb/logo.png", + "priceUsd": "0.03820927747439257" + }, + { + "chainId": 1, + "address": "0xc1D204d77861dEf49b6E769347a883B15EC397Ff", + "name": "PayperEx", + "symbol": "PAX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1601/thumb/pax.png?1547035800", + "priceUsd": "0.0018121837850960708" + }, + { + "chainId": 1, + "address": "0x45804880De22913dAFE09f4980848ECE6EcbAf78", + "name": "PAX Gold", + "symbol": "PAXG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9519/thumb/paxg.PNG?1568542565", + "priceUsd": "4024.69" + }, + { + "chainId": 1, + "address": "0x0D3CbED3f69EE050668ADF3D9Ea57241cBa33A2B", + "name": "PlayDapp", + "symbol": "PDA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14316/standard/PDA-symbol.png?1710234068", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x808507121B80c02388fAd14726482e061B8da827", + "name": "Pendle", + "symbol": "PENDLE", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/15069/large/Pendle_Logo_Normal-03.png?1696514728", + "priceUsd": "3.08" + }, + { + "chainId": 1, + "address": "0x6982508145454Ce325dDbE47a25d4ec3d2311933", + "name": "Pepe", + "symbol": "PEPE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/29850/large/pepe-token.jpeg?1682922725", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0xbC396689893D065F41bc2C6EcbeE5e0085233447", + "name": "Perpetual Protocol", + "symbol": "PERP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771", + "priceUsd": "0.196561" + }, + { + "chainId": 1, + "address": "0x7613C48E0cd50E42dD9Bf0f6c235063145f6f8DC", + "name": "Pirate Nation", + "symbol": "PIRATE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/38524/standard/_Pirate_Transparent_200x200.png", + "priceUsd": "0.01267211" + }, + { + "chainId": 1, + "address": "0xD8912C10681D8B21Fd3742244f44658dBA12264E", + "name": "Pluton", + "symbol": "PLU", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1241/thumb/pluton.png?1548331624", + "priceUsd": "0.3116218937032483" + }, + { + "chainId": 1, + "address": "0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6", + "name": "Polygon Ecosystem Token", + "symbol": "POL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/32440/large/polygon.png?1698233684", + "priceUsd": "0.187711" + }, + { + "chainId": 1, + "address": "0x83e6f1E41cdd28eAcEB20Cb649155049Fac3D5Aa", + "name": "Polkastarter", + "symbol": "POLS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12648/thumb/polkastarter.png?1609813702", + "priceUsd": "0.140324" + }, + { + "chainId": 1, + "address": "0x9992eC3cF6A55b00978cdDF2b27BC6882d88D1eC", + "name": "Polymath", + "symbol": "POLY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2784/thumb/inKkF01.png?1605007034", + "priceUsd": "0.03561919" + }, + { + "chainId": 1, + "address": "0x57B946008913B82E4dF85f501cbAeD910e58D26C", + "name": "Marlin", + "symbol": "POND", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/8903/thumb/POND_200x200.png?1622515451", + "priceUsd": "0.005509726254348523" + }, + { + "chainId": 1, + "address": "0x1Bbe973BeF3a977Fc51CbED703E8ffDEfE001Fed", + "name": "Portal", + "symbol": "PORTAL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/35436/standard/portal.jpeg", + "priceUsd": "0.024410679675373113" + }, + { + "chainId": 1, + "address": "0x595832F8FC6BF59c85C527fEC3740A1b7a361269", + "name": "Power Ledger", + "symbol": "POWR", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/1104/thumb/power-ledger.png?1547035082", + "priceUsd": "0.10689470424415419" + }, + { + "chainId": 1, + "address": "0xb23d80f5FefcDDaa212212F028021B41DEd428CF", + "name": "Prime", + "symbol": "PRIME", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/29053/large/PRIMELOGOOO.png?1676976222", + "priceUsd": "1.028" + }, + { + "chainId": 1, + "address": "0x226bb599a12C826476e3A771454697EA52E9E220", + "name": "Propy", + "symbol": "PRO", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/869/thumb/propy.png?1548332100", + "priceUsd": "0.564416" + }, + { + "chainId": 1, + "address": "0x6BEF15D938d4E72056AC92Ea4bDD0D76B1C4ad29", + "name": "Succinct", + "symbol": "PROVE", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/67905/large/succinct-logo.png?1754228574", + "priceUsd": "0.6990696727601527" + }, + { + "chainId": 1, + "address": "0x362bc847A3a9637d3af6624EeC853618a43ed7D2", + "name": "PARSIQ", + "symbol": "PRQ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11973/thumb/DsNgK0O.png?1596590280", + "priceUsd": "0.04498819039202485" + }, + { + "chainId": 1, + "address": "0xfB5c6815cA3AC72Ce9F5006869AE67f18bF77006", + "name": "pSTAKE Finance", + "symbol": "PSTAKE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/23931/thumb/PSTAKE_Dark.png?1645709930", + "priceUsd": "0.026341307561184493" + }, + { + "chainId": 1, + "address": "0x4d1C297d39C5c1277964D0E3f8Aa901493664530", + "name": "Puffer Finance", + "symbol": "PUFFER", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/50630/large/puffer.jpg?1728545297", + "priceUsd": "0.095418" + }, + { + "chainId": 1, + "address": "0x6c3ea9036406852006290770BEdFcAbA0e23A0e8", + "name": "PayPal USD", + "symbol": "PYUSD", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/31212/large/PYUSD_Logo_%282%29.png?1691458314", + "priceUsd": "0.999384" + }, + { + "chainId": 1, + "address": "0x4a220E6096B25EADb88358cb44068A3248254675", + "name": "Quant", + "symbol": "QNT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3370/thumb/5ZOu7brX_400x400.jpg?1612437252", + "priceUsd": "79.88" + }, + { + "chainId": 1, + "address": "0x4123a133ae3c521FD134D7b13A2dEC35b56c2463", + "name": "Qredo", + "symbol": "QRDO", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/17541/thumb/qrdo.png?1630637735", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x99ea4dB9EE77ACD40B119BD1dC4E33e1C070b80d", + "name": "Quantstamp", + "symbol": "QSP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1219/thumb/0_E0kZjb4dG4hUnoDD_.png?1604815917", + "priceUsd": "0.0014568855769206501" + }, + { + "chainId": 1, + "address": "0x6c28AeF8977c9B773996d0e8376d2EE379446F2f", + "name": "Quickswap", + "symbol": "QUICK", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13970/thumb/1_pOU6pBMEmiL-ZJVb0CYRjQ.png?1613386659", + "priceUsd": "18.614759435966693" + }, + { + "chainId": 1, + "address": "0x31c8EAcBFFdD875c74b94b077895Bd78CF1E64A3", + "name": "Radicle", + "symbol": "RAD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14013/thumb/radicle.png?1614402918", + "priceUsd": "0.459207" + }, + { + "chainId": 1, + "address": "0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919", + "name": "Rai Reflex Index", + "symbol": "RAI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14004/thumb/RAI-logo-coin.png?1613592334", + "priceUsd": "4.358066952898703" + }, + { + "chainId": 1, + "address": "0xba5BDe662c17e2aDFF1075610382B9B691296350", + "name": "SuperRare", + "symbol": "RARE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17753/thumb/RARE.jpg?1629220534", + "priceUsd": "0.033263984906634486" + }, + { + "chainId": 1, + "address": "0xFca59Cd816aB1eaD66534D82bc21E7515cE441CF", + "name": "Rarible", + "symbol": "RARI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11845/thumb/Rari.png?1594946953", + "priceUsd": "0.5688764642271458" + }, + { + "chainId": 1, + "address": "0xA4EED63db85311E22dF4473f87CcfC3DaDCFA3E3", + "name": "Rubic", + "symbol": "RBC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12629/thumb/200x200.png?1607952509", + "priceUsd": "0.0033343616064727276" + }, + { + "chainId": 1, + "address": "0x6123B0049F904d730dB3C36a31167D9d4121fA6B", + "name": "Ribbon Finance", + "symbol": "RBN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15823/thumb/RBN_64x64.png?1633529723", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0xc43C6bfeDA065fE2c4c11765Bf838789bd0BB5dE", + "name": "Redstone", + "symbol": "RED", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/53640/large/RedStone_Logo_New_White.png?1740640919", + "priceUsd": "0.319213" + }, + { + "chainId": 1, + "address": "0x408e41876cCCDC0F92210600ef50372656052a38", + "name": "Republic Token", + "symbol": "REN", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x408e41876cCCDC0F92210600ef50372656052a38/logo.png", + "priceUsd": "0.005625387339531064" + }, + { + "chainId": 1, + "address": "0x1985365e9f78359a9B6AD760e32412f4a445E862", + "name": "Reputation Augur v1", + "symbol": "REP", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1985365e9f78359a9B6AD760e32412f4a445E862/logo.png", + "priceUsd": "1.882768149383622" + }, + { + "chainId": 1, + "address": "0x221657776846890989a759BA2973e427DfF5C9bB", + "name": "Reputation Augur v2", + "symbol": "REPv2", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x221657776846890989a759BA2973e427DfF5C9bB/logo.png", + "priceUsd": "1.77" + }, + { + "chainId": 1, + "address": "0x8f8221aFbB33998d8584A2B05749bA73c37a938a", + "name": "Request", + "symbol": "REQ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1031/thumb/Request_icon_green.png?1643250951", + "priceUsd": "0.12304963062195665" + }, + { + "chainId": 1, + "address": "0x557B933a7C2c45672B610F8954A3deB39a51A8Ca", + "name": "REVV", + "symbol": "REVV", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12373/thumb/REVV_TOKEN_Refined_2021_%281%29.png?1627652390", + "priceUsd": "0.01937667216681617" + }, + { + "chainId": 1, + "address": "0x3B50805453023a91a8bf641e279401a0b23FA6F9", + "name": "Renzo", + "symbol": "REZ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/37327/standard/renzo_200x200.png?1714025012", + "priceUsd": "0.00841481" + }, + { + "chainId": 1, + "address": "0xD291E7a03283640FDc51b121aC401383A46cC623", + "name": "Rari Governance Token", + "symbol": "RGT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12900/thumb/Rari_Logo_Transparent.png?1613978014", + "priceUsd": "3.819915966314617" + }, + { + "chainId": 1, + "address": "0x607F4C5BB672230e8672085532f7e901544a7375", + "name": "iExec RLC", + "symbol": "RLC", + "decimals": 9, + "logoUrl": "https://assets.coingecko.com/coins/images/646/thumb/pL1VuXm.png?1604543202", + "priceUsd": "0.8178364063482229" + }, + { + "chainId": 1, + "address": "0x8292Bb45bf1Ee4d140127049757C2E0fF06317eD", + "name": "RLUSD", + "symbol": "RLUSD", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/39651/large/RLUSD_200x200_(1).png?1727376633", + "priceUsd": "0.999862" + }, + { + "chainId": 1, + "address": "0xf1f955016EcbCd7321c7266BccFB96c68ea5E49b", + "name": "Rally", + "symbol": "RLY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12843/thumb/image.png?1611212077", + "priceUsd": "0.000803659437000421" + }, + { + "chainId": 1, + "address": "0x6De037ef9aD2725EB40118Bb1702EBb27e4Aeb24", + "name": "Render Token", + "symbol": "RNDR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11636/thumb/rndr.png?1638840934", + "priceUsd": "2.26" + }, + { + "chainId": 1, + "address": "0xfA5047c9c78B8877af97BDcb85Db743fD7313d4a", + "name": "Rook", + "symbol": "ROOK", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13005/thumb/keeper_dao_logo.jpg?1604316506", + "priceUsd": "0.32649128722327414" + }, + { + "chainId": 1, + "address": "0xD33526068D116cE69F19A9ee46F0bd304F21A51f", + "name": "Rocket Pool Protocol", + "symbol": "RPL", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/2090/large/rocket_pool_%28RPL%29.png?1696503058", + "priceUsd": "3.24" + }, + { + "chainId": 1, + "address": "0x320623b8E4fF03373931769A31Fc52A4E78B5d70", + "name": "Reserve Rights", + "symbol": "RSR", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/8365/large/RSR_Blue_Circle_1000.png?1721777856", + "priceUsd": "0.00527529" + }, + { + "chainId": 1, + "address": "0x5aFE3855358E112B5647B952709E6165e1c1eEEe", + "name": "Safe", + "symbol": "SAFE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/27032/standard/Artboard_1_copy_8circle-1.png?1696526084", + "priceUsd": "0.227662" + }, + { + "chainId": 1, + "address": "0x3845badAde8e6dFF049820680d1F14bD3903a5d0", + "name": "The Sandbox", + "symbol": "SAND", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12129/thumb/sandbox_logo.jpg?1597397942", + "priceUsd": "0.201496" + }, + { + "chainId": 1, + "address": "0x30D20208d987713f46DFD34EF128Bb16C404D10f", + "name": "Stader", + "symbol": "SD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/20658/standard/SD_Token_Logo.png", + "priceUsd": "0.4268085419872386" + }, + { + "chainId": 1, + "address": "0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE", + "name": "Shiba Inu", + "symbol": "SHIB", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11939/thumb/shiba.png?1622619446", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x7C84e62859D0715eb77d1b1C4154Ecd6aBB21BEC", + "name": "Shping", + "symbol": "SHPING", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2588/thumb/r_yabKKi_400x400.jpg?1639470164", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x00c83aeCC790e8a4453e5dD3B0B4b3680501a7A7", + "name": "SKALE", + "symbol": "SKL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13245/thumb/SKALE_token_300x300.png?1606789574", + "priceUsd": "0.018571792151703192" + }, + { + "chainId": 1, + "address": "0x56072C95FAA701256059aa122697B133aDEd9279", + "name": "SKY Governance Token", + "symbol": "SKY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/39925/large/sky.jpg?1724827980", + "priceUsd": "0.056768" + }, + { + "chainId": 1, + "address": "0xCC8Fa225D80b9c7D42F96e9570156c65D6cAAa25", + "name": "Smooth Love Potion", + "symbol": "SLP", + "decimals": 0, + "logoUrl": "https://assets.coingecko.com/coins/images/10366/thumb/SLP.png?1578640057", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x744d70FDBE2Ba4CF95131626614a1763DF805B9E", + "name": "Status", + "symbol": "SNT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/779/thumb/status.png?1548610778", + "priceUsd": "0.01738148" + }, + { + "chainId": 1, + "address": "0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F", + "name": "Synthetix Network Token", + "symbol": "SNX", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png", + "priceUsd": "0.992672" + }, + { + "chainId": 1, + "address": "0x23B608675a2B2fB1890d3ABBd85c5775c51691d5", + "name": "Unisocks", + "symbol": "SOCKS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/10717/thumb/qFrcoiM.png?1582525244", + "priceUsd": "10318.303358562538" + }, + { + "chainId": 1, + "address": "0xD31a59c85aE9D8edEFeC411D448f90841571b89c", + "name": "SOL Wormhole ", + "symbol": "SOL", + "decimals": 9, + "logoUrl": "https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316", + "priceUsd": "187.06851638033984" + }, + { + "chainId": 1, + "address": "0x090185f2135308BaD17527004364eBcC2D37e5F6", + "name": "Spell Token", + "symbol": "SPELL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15861/thumb/abracadabra-3.png?1622544862", + "priceUsd": "0.0003174996511194724" + }, + { + "chainId": 1, + "address": "0xc20059e0317DE91738d13af027DfC4a50781b066", + "name": "Spark", + "symbol": "SPK", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/38637/large/Spark-Logomark-RGB.png?1744878896", + "priceUsd": "0.03500675" + }, + { + "chainId": 1, + "address": "0xE0f63A424a4439cBE457D80E4f4b51aD25b2c56C", + "name": "SPX6900", + "symbol": "SPX", + "decimals": 8, + "logoUrl": "https://coin-images.coingecko.com/coins/images/31401/large/sticker_(1).jpg?1702371083", + "priceUsd": "0.892328" + }, + { + "chainId": 1, + "address": "0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6", + "name": "Stargate Finance", + "symbol": "STG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24413/thumb/STG_LOGO.png?1647654518", + "priceUsd": "0.138351" + }, + { + "chainId": 1, + "address": "0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC", + "name": "Storj Token", + "symbol": "STORJ", + "decimals": 8, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC/logo.png", + "priceUsd": "0.16743627553422577" + }, + { + "chainId": 1, + "address": "0xCa14007Eff0dB1f8135f4C25B34De49AB0d42766", + "name": "Starknet", + "symbol": "STRK", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/26433/standard/starknet.png?1696525507", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x006BeA43Baa3f7A6f765F14f10A1a1b08334EF45", + "name": "Stox", + "symbol": "STX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1230/thumb/stox-token.png?1547035256", + "priceUsd": "0.00773281" + }, + { + "chainId": 1, + "address": "0x0763fdCCF1aE541A5961815C0872A8c5Bc6DE4d7", + "name": "SUKU", + "symbol": "SUKU", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11969/thumb/UmfW5S6f_400x400.jpg?1596602238", + "priceUsd": "0.023236718270571336" + }, + { + "chainId": 1, + "address": "0xe53EC727dbDEB9E2d5456c3be40cFF031AB40A55", + "name": "SuperFarm", + "symbol": "SUPER", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14040/thumb/6YPdWn6.png?1613975899", + "priceUsd": "0.363994" + }, + { + "chainId": 1, + "address": "0x57Ab1ec28D129707052df4dF418D58a2D46d5f51", + "name": "Synth sUSD", + "symbol": "sUSD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/5013/thumb/sUSD.png?1616150765", + "priceUsd": "0.983694" + }, + { + "chainId": 1, + "address": "0x6B3595068778DD592e39A122f4f5a5cF09C90fE2", + "name": "Sushi", + "symbol": "SUSHI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688", + "priceUsd": "0.491045" + }, + { + "chainId": 1, + "address": "0x0a6E7Ba5042B38349e437ec6Db6214AEC7B35676", + "name": "Swell", + "symbol": "SWELL", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/28777/large/swell1.png?1727899715", + "priceUsd": "0.0054606188123819495" + }, + { + "chainId": 1, + "address": "0x0bb217E40F8a5Cb79Adf04E1aAb60E5abd0dfC1e", + "name": "SWFTCOIN", + "symbol": "SWFTC", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/2346/thumb/SWFTCoin.jpg?1618392022", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x8CE9137d39326AD0cD6491fb5CC0CbA0e089b6A9", + "name": "Swipe", + "symbol": "SXP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9368/thumb/swipe.png?1566792311", + "priceUsd": "0.038872710914027525" + }, + { + "chainId": 1, + "address": "0xE6Bfd33F52d82Ccb5b37E16D3dD81f9FFDAbB195", + "name": "Space and Time", + "symbol": "SXT", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/55424/large/sxt-token_circle.jpg?1745935919", + "priceUsd": "0.05239379981792088" + }, + { + "chainId": 1, + "address": "0xf293d23BF2CDc05411Ca0edDD588eb1977e8dcd4", + "name": "Sylo", + "symbol": "SYLO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/6430/thumb/SYLO.svg?1589527756", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x0f2D719407FdBeFF09D87557AbB7232601FD9F29", + "name": "Synapse", + "symbol": "SYN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/18024/thumb/syn.png?1635002049", + "priceUsd": "0.07677105586189172" + }, + { + "chainId": 1, + "address": "0x643C4E15d7d62Ad0aBeC4a9BD4b001aA3Ef52d66", + "name": "Syrup Token", + "symbol": "SYRUP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/51232/standard/IMG_7420.png?1730831572", + "priceUsd": "0.419465" + }, + { + "chainId": 1, + "address": "0xCdF7028ceAB81fA0C6971208e83fa7872994beE5", + "name": "Threshold Network", + "symbol": "T", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/22228/thumb/nFPNiSbL_400x400.jpg?1641220340", + "priceUsd": "0.01233784" + }, + { + "chainId": 1, + "address": "0x18084fbA666a33d37592fA2633fD49a74DD93a88", + "name": "tBTC", + "symbol": "tBTC", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/uniswap/assets/master/blockchains/ethereum/assets/0x18084fbA666a33d37592fA2633fD49a74DD93a88/logo.png", + "priceUsd": "109597" + }, + { + "chainId": 1, + "address": "0xC3d21f79C3120A4fFda7A535f8005a7c297799bF", + "name": "Term Finance", + "symbol": "TERM", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/38142/large/terms.png?1716630303", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x485d17A6f1B8780392d53D64751824253011A260", + "name": "ChronoTech", + "symbol": "TIME", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/604/thumb/time-32x32.png?1627130666", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x888888848B652B3E3a0f34c96E00EEC0F3a23F72", + "name": "Alien Worlds", + "symbol": "TLM", + "decimals": 4, + "logoUrl": "https://assets.coingecko.com/coins/images/14676/thumb/kY-C4o7RThfWrDQsLCAG4q4clZhBDDfJQVhWUEKxXAzyQYMj4Jmq1zmFwpRqxhAJFPOa0AsW_PTSshoPuMnXNwq3rU7Imp15QimXTjlXMx0nC088mt1rIwRs75GnLLugWjSllxgzvQ9YrP4tBgclK4_rb17hjnusGj_c0u2fx0AvVokjSNB-v2poTj0xT9BZRCbzRE3-lF1.jpg?1617700061", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x2e9d63788249371f1DFC918a52f8d799F4a38C94", + "name": "Tokemak", + "symbol": "TOKE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17495/thumb/tokemak-avatar-200px-black.png?1628131614", + "priceUsd": "0.191698" + }, + { + "chainId": 1, + "address": "0x4507cEf57C46789eF8d1a19EA45f4216bae2B528", + "name": "TokenFi", + "symbol": "TOKEN", + "decimals": 9, + "logoUrl": "https://coin-images.coingecko.com/coins/images/32507/large/MAIN_TokenFi_logo_icon.png?1698918427", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x2Ab6Bb8408ca3199B8Fa6C92d5b455F820Af03c4", + "name": "TE FOOD", + "symbol": "TONE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2325/thumb/tec.png?1547036538", + "priceUsd": "0.000631742027737446" + }, + { + "chainId": 1, + "address": "0xaA7a9CA87d3694B5755f213B5D04094b8d0F0A6F", + "name": "OriginTrail", + "symbol": "TRAC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1877/thumb/TRAC.jpg?1635134367", + "priceUsd": "0.650831" + }, + { + "chainId": 1, + "address": "0x88dF592F8eb5D7Bd38bFeF7dEb0fBc02cf3778a0", + "name": "Tellor", + "symbol": "TRB", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9644/thumb/Blk_icon_current.png?1584980686", + "priceUsd": "25.515557373406907" + }, + { + "chainId": 1, + "address": "0x77146784315Ba81904d654466968e3a7c196d1f3", + "name": "Treehouse Token", + "symbol": "TREE", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/67664/large/TREE_logo.png?1753601041", + "priceUsd": "0.166197" + }, + { + "chainId": 1, + "address": "0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B", + "name": "Tribe", + "symbol": "TRIBE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14575/thumb/tribe.PNG?1617487954", + "priceUsd": "0.655145" + }, + { + "chainId": 1, + "address": "0x4C19596f5aAfF459fA38B0f7eD92F11AE6543784", + "name": "TrueFi", + "symbol": "TRU", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/13180/thumb/truefi_glyph_color.png?1617610941", + "priceUsd": "0.01811374277404015" + }, + { + "chainId": 1, + "address": "0xA35923162C49cF95e6BF26623385eb431ad920D3", + "name": "Turbo", + "symbol": "TURBO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/30117/large/TurboMark-QL_200.png?1708079597", + "priceUsd": "0.00218358" + }, + { + "chainId": 1, + "address": "0xd084B83C305daFD76AE3E1b4E1F1fe2eCcCb3988", + "name": "The Virtua Kolect", + "symbol": "TVK", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13330/thumb/virtua_original.png?1656043619", + "priceUsd": "0.015169335022930155" + }, + { + "chainId": 1, + "address": "0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828", + "name": "UMA Voting Token v1", + "symbol": "UMA", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828/logo.png", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x441761326490cACF7aF299725B6292597EE822c2", + "name": "Unifi Protocol DAO", + "symbol": "UNFI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13152/thumb/logo-2.png?1605748967", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984", + "name": "Uniswap", + "symbol": "UNI", + "decimals": 18, + "logoUrl": "ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg", + "priceUsd": "5.75" + }, + { + "chainId": 1, + "address": "0x70D2b7C19352bB76e4409858FF5746e500f2B67c", + "name": "Pawtocol", + "symbol": "UPI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12186/thumb/pawtocol.jpg?1597962008", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d", + "name": "World Liberty Financial USD", + "symbol": "USD1", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/54977/large/USD1_1000x1000_transparent.png?1749297002", + "priceUsd": "0.999389" + }, + { + "chainId": 1, + "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + "name": "USDCoin", + "symbol": "USDC", + "decimals": 6, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png", + "priceUsd": "0.999803" + }, + { + "chainId": 1, + "address": "0xe343167631d89B6Ffc58B88d6b7fB0228795491D", + "name": "Global Dollar", + "symbol": "USDG", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/51281/large/GDN_USDG_Token_200x200.png", + "priceUsd": "0.999812" + }, + { + "chainId": 1, + "address": "0x8E870D67F660D95d5be530380D0eC0bd388289E1", + "name": "Pax Dollar", + "symbol": "USDP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/6013/standard/Pax_Dollar.png?1696506427", + "priceUsd": "1.4197491072192059" + }, + { + "chainId": 1, + "address": "0xc83e27f270cce0A3A3A29521173a83F402c1768b", + "name": "Quantoz USDQ", + "symbol": "USDQ", + "decimals": 6, + "logoUrl": "https://coin-images.coingecko.com/coins/images/51852/large/USDQ_1000px_Color.png?1732071232", + "priceUsd": "0.999765" + }, + { + "chainId": 1, + "address": "0x7B43E3875440B44613DC3bC08E7763e6Da63C8f8", + "name": "StablR USD", + "symbol": "USDR", + "decimals": 6, + "logoUrl": "https://coin-images.coingecko.com/coins/images/53721/large/stablrusd-logo.png?1737126629", + "priceUsd": "0.999722" + }, + { + "chainId": 1, + "address": "0xdC035D45d973E3EC169d2276DDab16f1e407384F", + "name": "USDS Stablecoin", + "symbol": "USDS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/39926/large/usds.webp?1726666683", + "priceUsd": "0.999757" + }, + { + "chainId": 1, + "address": "0xdAC17F958D2ee523a2206206994597C13D831ec7", + "name": "Tether USD", + "symbol": "USDT", + "decimals": 6, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png", + "priceUsd": "0.99984" + }, + { + "chainId": 1, + "address": "0xC4441c2BE5d8fA8126822B9929CA0b81Ea0DE38E", + "name": "USUAL", + "symbol": "USUAL", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/51091/large/USUAL.jpg?1730035787", + "priceUsd": "0.02942148" + }, + { + "chainId": 1, + "address": "0x8DE5B80a0C1B02Fe4976851D030B36122dbb8624", + "name": "VANRY", + "symbol": "VANRY", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/33466/large/apple-touch-icon.png?1701942541", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x3C4B6E6e1eA3D4863700D7F76b36B7f3D3f13E3d", + "name": "Voyager Token", + "symbol": "VGX", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/794/thumb/Voyager-vgx.png?1575693595", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0xEDB171C18cE90B633DB442f2A6F72874093b49Ef", + "name": "Wrapped Ampleforth", + "symbol": "WAMPL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/20825/thumb/photo_2021-11-25_02-05-11.jpg?1637811951", + "priceUsd": "1.820752524001557" + }, + { + "chainId": 1, + "address": "0xf983da3ca66964C02628189Ea8Ca99fa9E24f66c", + "name": "Wrapped Analog One Token", + "symbol": "WANLOG", + "decimals": 12, + "logoUrl": "https://assets.kraken.com/marketing/web/icons-uni-webp/s_anlog.webp?i=kds", + "priceUsd": "0.0013041584406022066" + }, + { + "chainId": 1, + "address": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", + "name": "Wrapped BTC", + "symbol": "WBTC", + "decimals": 8, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png", + "priceUsd": "109562" + }, + { + "chainId": 1, + "address": "0xc221b7E65FfC80DE234bbB6667aBDd46593D34F0", + "name": "Wrapped Centrifuge", + "symbol": "WCFG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17106/thumb/WCFG.jpg?1626266462", + "priceUsd": "0.29885478698868867" + }, + { + "chainId": 1, + "address": "0xeF4461891DfB3AC8572cCf7C794664A8DD927945", + "name": "WalletConnect Token", + "symbol": "WCT", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/50390/large/wc-token1.png?1727569464", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "name": "Wrapped Ether", + "symbol": "WETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3847.11" + }, + { + "chainId": 1, + "address": "0xdA5e1988097297dCdc1f90D4dFE7909e847CBeF6", + "name": "World Liberty Financial", + "symbol": "WLFI", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/50767/large/wlfi.png?1756438915", + "priceUsd": "0.135757" + }, + { + "chainId": 1, + "address": "0x4691937a7508860F876c9c0a2a617E7d9E945D4B", + "name": "WOO Network", + "symbol": "WOO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12921/thumb/w2UiemF__400x400.jpg?1603670367", + "priceUsd": "0.0371699" + }, + { + "chainId": 1, + "address": "0xA2cd3D43c775978A96BdBf12d733D5A1ED94fb18", + "name": "Chain", + "symbol": "XCN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24210/thumb/Chain_icon_200x200.png?1646895054", + "priceUsd": "0.00832302" + }, + { + "chainId": 1, + "address": "0x70e8dE73cE538DA2bEEd35d14187F6959a8ecA96", + "name": "XSGD", + "symbol": "XSGD", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/12832/standard/StraitsX_Singapore_Dollar_%28XSGD%29_Token_Logo.png?1696512623", + "priceUsd": "0.76843" + }, + { + "chainId": 1, + "address": "0x55296f69f40Ea6d20E478533C15A6B08B654E758", + "name": "XYO Network", + "symbol": "XYO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4519/thumb/XYO_Network-logo.png?1547039819", + "priceUsd": "0.00697017" + }, + { + "chainId": 1, + "address": "0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e", + "name": "yearn finance", + "symbol": "YFI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330", + "priceUsd": "4665.62" + }, + { + "chainId": 1, + "address": "0xa1d0E215a23d7030842FC67cE582a6aFa3CCaB83", + "name": "DFI money", + "symbol": "YFII", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11902/thumb/YFII-logo.78631676.png?1598677348", + "priceUsd": "67.48851832114867" + }, + { + "chainId": 1, + "address": "0x25f8087EAD173b73D6e8B84329989A8eEA16CF73", + "name": "Yield Guild Games", + "symbol": "YGG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17358/thumb/le1nzlO6_400x400.jpg?1632465691", + "priceUsd": "0.118472" + }, + { + "chainId": 1, + "address": "0xf091867EC603A6628eD83D274E835539D82e9cc8", + "name": "Zetachain", + "symbol": "Zeta", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/26718/standard/Twitter_icon.png?1696525788", + "priceUsd": "0.11463388574922474" + }, + { + "chainId": 1, + "address": "0x6985884C4392D348587B19cb9eAAf157F13271cd", + "name": "LayerZero", + "symbol": "ZRO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208", + "priceUsd": "1.54" + }, + { + "chainId": 1, + "address": "0xE41d2489571d322189246DaFA5ebDe1F4699F498", + "name": "0x Protocol Token", + "symbol": "ZRX", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png", + "priceUsd": "0.18600767043832045" + }, + { + "chainId": 10, + "address": "0x76FB31fb4af56892A25e32cFC43De717950c9278", + "name": "Aave", + "symbol": "AAVE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110", + "priceUsd": "218.02" + }, + { + "chainId": 10, + "address": "0x9C9e5fD8bbc25984B178FdCE6117Defa39d2db39", + "name": "Binance USD", + "symbol": "BUSD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766", + "priceUsd": "0.8999945686003405" + }, + { + "chainId": 10, + "address": "0x9b88D293b7a791E40d36A39765FFd5A1B9b5c349", + "name": "Celo native asset (Wormhole)", + "symbol": "CELO", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/wormhole-foundation/wormhole-token-list/main/assets/celo_wh.png", + "priceUsd": null + }, + { + "chainId": 10, + "address": "0x14778860E937f509e651192a90589dE711Fb88a9", + "name": "CYBER", + "symbol": "CYBER", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/31274/large/token.png?1715826754", + "priceUsd": "1.5762440253446286" + }, + { + "chainId": 10, + "address": "0x33800De7E817A70A694F31476313A7c572BBa100", + "name": "Derive", + "symbol": "DRV", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/52889/large/Token_Logo.png?1734601695", + "priceUsd": "0.03385757" + }, + { + "chainId": 10, + "address": "0x3A18dcC9745eDcD1Ef33ecB93b0b6eBA5671e7Ca", + "name": "Kujira", + "symbol": "KUJI", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/20685/standard/kuji-200x200.png", + "priceUsd": null + }, + { + "chainId": 10, + "address": "0x4200000000000000000000000000000000000042", + "name": "Optimism", + "symbol": "OP", + "decimals": 18, + "logoUrl": "https://ethereum-optimism.github.io/data/OP/logo.png", + "priceUsd": "0.399683" + }, + { + "chainId": 10, + "address": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85", + "name": "USDCoin", + "symbol": "USDC", + "decimals": 6, + "logoUrl": "https://ethereum-optimism.github.io/data/USDC/logo.png", + "priceUsd": "0.999803" + }, + { + "chainId": 10, + "address": "0x7F5c764cBc14f9669B88837ca1490cCa17c31607", + "name": "USDCoin (Bridged from Ethereum)", + "symbol": "USDC.e", + "decimals": 6, + "logoUrl": "https://ethereum-optimism.github.io/data/USDC/logo.png", + "priceUsd": "0.999769" + }, + { + "chainId": 10, + "address": "0x9560e827aF36c94D2Ac33a39bCE1Fe78631088Db", + "name": "Velodrome Finance", + "symbol": "VELO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12538/standard/Logo_200x_200.png?1696512350", + "priceUsd": "0.03342802" + }, + { + "chainId": 10, + "address": "0xeF4461891DfB3AC8572cCf7C794664A8DD927945", + "name": "WalletConnect Token", + "symbol": "WCT", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/50390/large/wc-token1.png?1727569464", + "priceUsd": null + }, + { + "chainId": 10, + "address": "0x4200000000000000000000000000000000000006", + "name": "Wrapped Ether", + "symbol": "WETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3847.11" + }, + { + "chainId": 10, + "address": "0xdC6fF44d5d932Cbd77B52E5612Ba0529DC6226F1", + "name": "Worldcoin", + "symbol": "WLD", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/31069/large/worldcoin.jpeg?1696529903", + "priceUsd": "0.799409" + }, + { + "chainId": 10, + "address": "0x6985884C4392D348587B19cb9eAAf157F13271cd", + "name": "LayerZero", + "symbol": "ZRO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208", + "priceUsd": "1.54" + }, + { + "chainId": 56, + "address": "0x111111111117dC0aa78b770fA6A738034120C302", + "name": "1inch", + "symbol": "1INCH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028", + "priceUsd": "0.16034860758378902" + }, + { + "chainId": 56, + "address": "0xfb6115445Bff7b52FeB98650C87f44907E58f802", + "name": "Aave", + "symbol": "AAVE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110", + "priceUsd": "218.02" + }, + { + "chainId": 56, + "address": "0xBc7d6B50616989655AfD682fb42743507003056D", + "name": "Alchemy Pay", + "symbol": "ACH", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/12390/thumb/ACH_%281%29.png?1599691266", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x6bfF4Fb161347ad7de4A625AE5aa3A1CA7077819", + "name": "Ambire AdEx", + "symbol": "ADX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/847/thumb/Ambire_AdEx_Symbol_color.png?1655432540", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x12f31B73D812C6Bb0d735a218c086d44D5fe5f89", + "name": "agEur", + "symbol": "agEUR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19479/standard/agEUR.png?1696518915", + "priceUsd": "1.15" + }, + { + "chainId": 56, + "address": "0x33d08D8C7a168333a85285a68C0042b39fC3741D", + "name": "AIOZ Network", + "symbol": "AIOZ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14631/thumb/aioz_logo.png?1617413126", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x82D2f8E02Afb160Dd5A480a617692e62de9038C4", + "name": "Aleph im", + "symbol": "ALEPH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11676/thumb/Monochram-aleph.png?1608483725", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0xAC51066d7bEC65Dc4589368da368b212745d63E8", + "name": "My Neighbor Alice", + "symbol": "ALICE", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/14375/thumb/alice_logo.jpg?1615782968", + "priceUsd": "0.278582" + }, + { + "chainId": 56, + "address": "0xa1faa113cbE53436Df28FF0aEe54275c13B40975", + "name": "Alpha Venture DAO", + "symbol": "ALPHA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12738/thumb/AlphaToken_256x256.png?1617160876", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0xf307910A4c7bbc79691fD374889b36d8531B08e3", + "name": "Ankr", + "symbol": "ANKR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4324/thumb/U85xTl2.png?1608111978", + "priceUsd": "0.00960243290914454" + }, + { + "chainId": 56, + "address": "0x6F769E65c14Ebd1f68817F5f1DcDb61Cfa2D6f7e", + "name": "ARPA Chain", + "symbol": "ARPA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/8506/thumb/9u0a23XY_400x400.jpg?1559027357", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0xA2120b9e674d3fC3875f415A7DF52e382F141225", + "name": "Automata", + "symbol": "ATA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15985/thumb/ATA.jpg?1622535745", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x8b1f4432F943c465A973FeDC6d7aa50Fc96f1f65", + "name": "Axelar", + "symbol": "AXL", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/27277/large/V-65_xQ1_400x400.jpeg", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x715D400F88C167884bbCc41C5FeA407ed4D2f8A0", + "name": "Axie Infinity", + "symbol": "AXS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13029/thumb/axie_infinity_logo.png?1604471082", + "priceUsd": "1.4365824126955422" + }, + { + "chainId": 56, + "address": "0x935a544Bf5816E3A7C13DB2EFe3009Ffda0aCdA2", + "name": "Bluzelle", + "symbol": "BLZ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2848/thumb/ColorIcon_3x.png?1622516510", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56", + "name": "Binance USD", + "symbol": "BUSD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766", + "priceUsd": "0.999151" + }, + { + "chainId": 56, + "address": "0xaEC945e04baF28b135Fa7c640f624f8D90F1C3a6", + "name": "Coin98", + "symbol": "C98", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17117/thumb/logo.png?1626412904", + "priceUsd": "0.03402936" + }, + { + "chainId": 56, + "address": "0xf9CeC8d50f6c8ad3Fb6dcCEC577e05aA32B224FE", + "name": "Chromia", + "symbol": "CHR", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/5000/thumb/Chromia.png?1559038018", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x09E889BB4D5b474f561db0491C38702F367A4e4d", + "name": "Clover Finance", + "symbol": "CLV", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15278/thumb/clover.png?1645084454", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x52CE071Bd9b1C4B00A0b92D298c512478CaD67e8", + "name": "Compound", + "symbol": "COMP", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png", + "priceUsd": "34.79870220047158" + }, + { + "chainId": 56, + "address": "0xd15CeE1DEaFBad6C0B3Fd7489677Cc102B141464", + "name": "Circuits of Value", + "symbol": "COVAL", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/588/thumb/coval-logo.png?1599493950", + "priceUsd": "0.00046639" + }, + { + "chainId": 56, + "address": "0x8dA443F84fEA710266C8eB6bC34B71702d033EF2", + "name": "Cartesi", + "symbol": "CTSI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3", + "name": "Dai Stablecoin", + "symbol": "DAI", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png", + "priceUsd": "1" + }, + { + "chainId": 56, + "address": "0x23CE9e926048273eF83be0A3A8Ba9Cb6D45cd978", + "name": "Mines of Dalarnia", + "symbol": "DAR", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/19837/thumb/dar.png?1636014223", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0xe91a8D2c584Ca93C7405F15c22CdFE53C29896E3", + "name": "DexTools", + "symbol": "DEXT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11603/thumb/dext.png?1605790188", + "priceUsd": "0.3213964411864532" + }, + { + "chainId": 56, + "address": "0x99956D38059cf7bEDA96Ec91Aa7BB2477E0901DD", + "name": "DIA", + "symbol": "DIA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11955/thumb/image.png?1646041751", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0xEC583f25A049CC145dA9A256CDbE9B6201a705Ff", + "name": "Drep", + "symbol": "DREP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14578/thumb/KotgsCgS_400x400.jpg?1617094445", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x961C8c0B1aaD0c0b10a51FeF6a867E3091BCef17", + "name": "DeFi Yield Protocol", + "symbol": "DYP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13480/thumb/DYP_Logo_Symbol-8.png?1655809066", + "priceUsd": "0.0401301046925173" + }, + { + "chainId": 56, + "address": "0x7bd6FaBD64813c48545C9c0e312A0099d9be2540", + "name": "Dogelon Mars", + "symbol": "ELON", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14962/thumb/6GxcPRo3_400x400.jpg?1619157413", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x4B5C23cac08a567ecf0c1fFcA8372A45a5D33743", + "name": "Harvest Finance", + "symbol": "FARM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12304/thumb/Harvest.png?1613016180", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x031b41e504677879370e9DBcF937283A8691Fa7f", + "name": "Fetch ai", + "symbol": "FET", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/5681/thumb/Fetch.jpg?1572098136", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0xfb5B838b6cfEEdC2873aB27866079AC55363D37E", + "name": "FLOKI", + "symbol": "FLOKI", + "decimals": 9, + "logoUrl": "https://assets.coingecko.com/coins/images/16746/standard/PNG_image.png?1696516318", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x90C97F71E18723b0Cf0dfa30ee176Ab653E89F40", + "name": "Frax", + "symbol": "FRAX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13422/thumb/frax_logo.png?1608476506", + "priceUsd": "0.9847649299461979" + }, + { + "chainId": 56, + "address": "0xAD29AbB318791D579433D831ed122aFeAf29dcfe", + "name": "Fantom", + "symbol": "FTM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4001/thumb/Fantom.png?1558015016", + "priceUsd": "0.14114234565194506" + }, + { + "chainId": 56, + "address": "0xe48A3d7d0Bc88d552f730B62c006bC925eadB9eE", + "name": "Frax Share", + "symbol": "FXS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13423/thumb/frax_share.png?1608478989", + "priceUsd": "1.2296844443935946" + }, + { + "chainId": 56, + "address": "0xe4Cc45Bb5DBDA06dB6183E8bf016569f40497Aa5", + "name": "Galxe", + "symbol": "GAL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24530/thumb/GAL-Token-Icon.png?1651483533", + "priceUsd": "0.4452147915319493" + }, + { + "chainId": 56, + "address": "0x44Ec807ce2F4a6F2737A92e985f318d035883e47", + "name": "Hashflow", + "symbol": "HFT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/26136/large/hashflow-icon-cmc.png", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x5f4Bde007Dc06b867f86EBFE4802e34A1fFEEd63", + "name": "Highstreet", + "symbol": "HIGH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/18973/thumb/logosq200200Coingecko.png?1634090470", + "priceUsd": "0.28413088647684537" + }, + { + "chainId": 56, + "address": "0xa2B726B1145A4773F68593CF171187d8EBe4d495", + "name": "Injective", + "symbol": "INJ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12882/thumb/Secondary_Symbol.png?1628233237", + "priceUsd": "7.66" + }, + { + "chainId": 56, + "address": "0x0231f91e02DebD20345Ae8AB7D71A41f8E140cE7", + "name": "Jupiter", + "symbol": "JUP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/10351/thumb/logo512.png?1632480932", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x073690e6CE25bE816E68F32dCA3e11067c9FB5Cc", + "name": "Kujira", + "symbol": "KUJI", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/20685/standard/kuji-200x200.png", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD", + "name": "ChainLink Token", + "symbol": "LINK", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png", + "priceUsd": "17.15" + }, + { + "chainId": 56, + "address": "0x2eD9a5C8C13b93955103B9a7C167B67Ef4d568a3", + "name": "Mask Network", + "symbol": "MASK", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14051/thumb/Mask_Network.jpg?1614050316", + "priceUsd": "0.8049154805639249" + }, + { + "chainId": 56, + "address": "0xF218184Af829Cf2b0019F8E6F0b2423498a36983", + "name": "MATH", + "symbol": "MATH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11335/thumb/2020-05-19-token-200.png?1589940590", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0xCC42724C6683B7E57334c4E856f4c9965ED682bD", + "name": "Polygon", + "symbol": "MATIC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912", + "priceUsd": "0.1884564184605192" + }, + { + "chainId": 56, + "address": "0x949D48EcA67b17269629c7194F4b727d4Ef9E5d6", + "name": "Merit Circle", + "symbol": "MC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19304/thumb/Db4XqML.png?1634972154", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0xe552Fb52a4F19e44ef5A967632DBc320B0820639", + "name": "Metis", + "symbol": "METIS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15595/thumb/metis.jpeg?1660285312", + "priceUsd": "0.007680670050509777" + }, + { + "chainId": 56, + "address": "0xfE19F0B51438fd612f6FD59C1dbB3eA319f433Ba", + "name": "Magic Internet Money", + "symbol": "MIM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/16786/thumb/mimlogopng.png?1624979612", + "priceUsd": "1.0017575701915018" + }, + { + "chainId": 56, + "address": "0x5B6DcF557E2aBE2323c48445E8CC948910d8c2c9", + "name": "Mirror Protocol", + "symbol": "MIR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13295/thumb/mirror_logo_transparent.png?1611554658", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x9Fb9a33956351cf4fa040f65A13b835A3C8764E3", + "name": "Multichain", + "symbol": "MULTI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/22087/thumb/1_Wyot-SDGZuxbjdkaOeT2-A.png?1640764238", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x4e7f408be2d4E9D60F49A64B89Bb619c84C7c6F5", + "name": "Perpetual Protocol", + "symbol": "PERP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x7e624FA0E1c4AbFD309cC15719b7E2580887f570", + "name": "Polkastarter", + "symbol": "POLS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12648/thumb/polkastarter.png?1609813702", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0xd21d29B38374528675C34936bf7d5Dd693D2a577", + "name": "PARSIQ", + "symbol": "PRQ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11973/thumb/DsNgK0O.png?1596590280", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x4C882ec256823eE773B25b414d36F92ef58a7c0C", + "name": "pSTAKE Finance", + "symbol": "PSTAKE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/23931/thumb/PSTAKE_Dark.png?1645709930", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x833F307aC507D47309fD8CDD1F835BeF8D702a93", + "name": "REVV", + "symbol": "REVV", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12373/thumb/REVV_TOKEN_Refined_2021_%281%29.png?1627652390", + "priceUsd": "0.0022625233412220816" + }, + { + "chainId": 56, + "address": "0x3BC5AC0dFdC871B365d159f728dd1B9A0B5481E8", + "name": "Stader", + "symbol": "SD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/20658/standard/SD_Token_Logo.png", + "priceUsd": "0.4168017154807315" + }, + { + "chainId": 56, + "address": "0xfA54fF1a158B5189Ebba6ae130CEd6bbd3aEA76e", + "name": "SOL Wormhole ", + "symbol": "SOL", + "decimals": 9, + "logoUrl": "https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0xB0D502E938ed5f4df2E681fE6E419ff29631d62b", + "name": "Stargate Finance", + "symbol": "STG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24413/thumb/STG_LOGO.png?1647654518", + "priceUsd": "0.13872352248162545" + }, + { + "chainId": 56, + "address": "0x51BA0b044d96C3aBfcA52B64D733603CCC4F0d4D", + "name": "SuperFarm", + "symbol": "SUPER", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14040/thumb/6YPdWn6.png?1613975899", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x947950BcC74888a40Ffa2593C5798F11Fc9124C4", + "name": "Sushi", + "symbol": "SUSHI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688", + "priceUsd": "0.49170536834534717" + }, + { + "chainId": 56, + "address": "0xE64E30276C2F826FEbd3784958d6Da7B55DfbaD3", + "name": "SWFTCOIN", + "symbol": "SWFTC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2346/thumb/SWFTCoin.jpg?1618392022", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x47BEAd2563dCBf3bF2c9407fEa4dC236fAbA485A", + "name": "Swipe", + "symbol": "SXP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9368/thumb/swipe.png?1566792311", + "priceUsd": "0.01787910261158916" + }, + { + "chainId": 56, + "address": "0xa4080f1778e69467E905B8d6F72f6e441f9e9484", + "name": "Synapse", + "symbol": "SYN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/18024/thumb/syn.png?1635002049", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x3b198e26E473b8faB2085b37978e36c9DE5D7f68", + "name": "ChronoTech", + "symbol": "TIME", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/604/thumb/time-32x32.png?1627130666", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x2222227E22102Fe3322098e4CBfE18cFebD57c95", + "name": "Alien Worlds", + "symbol": "TLM", + "decimals": 4, + "logoUrl": "https://assets.coingecko.com/coins/images/14676/thumb/kY-C4o7RThfWrDQsLCAG4q4clZhBDDfJQVhWUEKxXAzyQYMj4Jmq1zmFwpRqxhAJFPOa0AsW_PTSshoPuMnXNwq3rU7Imp15QimXTjlXMx0nC088mt1rIwRs75GnLLugWjSllxgzvQ9YrP4tBgclK4_rb17hjnusGj_c0u2fx0AvVokjSNB-v2poTj0xT9BZRCbzRE3-lF1.jpg?1617700061", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x728C5baC3C3e370E372Fc4671f9ef6916b814d8B", + "name": "Unifi Protocol DAO", + "symbol": "UNFI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13152/thumb/logo-2.png?1605748967", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0xBf5140A22578168FD562DCcF235E5D43A02ce9B1", + "name": "Uniswap", + "symbol": "UNI", + "decimals": 18, + "logoUrl": "ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg", + "priceUsd": "5.75" + }, + { + "chainId": 56, + "address": "0x0D35A2B85c5A63188d566D104bEbf7C694334Ee4", + "name": "Pawtocol", + "symbol": "UPI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12186/thumb/pawtocol.jpg?1597962008", + "priceUsd": "0.016804914246989534" + }, + { + "chainId": 56, + "address": "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d", + "name": "USDCoin", + "symbol": "USDC", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png", + "priceUsd": "1" + }, + { + "chainId": 56, + "address": "0x55d398326f99059fF775485246999027B3197955", + "name": "Tether USD", + "symbol": "USDT", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png", + "priceUsd": "0.999749" + }, + { + "chainId": 56, + "address": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", + "name": "Wrapped BNB", + "symbol": "WBNB", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/smartchain/assets/0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c/logo.png", + "priceUsd": "1080.71" + }, + { + "chainId": 56, + "address": "0x2170Ed0880ac9A755fd29B2688956BD959F933F8", + "name": "Wrapped Ether", + "symbol": "WETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3848.03" + }, + { + "chainId": 56, + "address": "0x4691937a7508860F876c9c0a2a617E7d9E945D4B", + "name": "WOO Network", + "symbol": "WOO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12921/thumb/w2UiemF__400x400.jpg?1603670367", + "priceUsd": "0.03709461989277745" + }, + { + "chainId": 56, + "address": "0x7324c7C0d95CEBC73eEa7E85CbAac0dBdf88a05b", + "name": "Chain", + "symbol": "XCN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24210/thumb/Chain_icon_200x200.png?1646895054", + "priceUsd": null + }, + { + "chainId": 56, + "address": "0x6985884C4392D348587B19cb9eAAf157F13271cd", + "name": "LayerZero", + "symbol": "ZRO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208", + "priceUsd": "1.55" + }, + { + "chainId": 130, + "address": "0xbe41cde1C5e75a7b6c2c70466629878aa9ACd06E", + "name": "1inch", + "symbol": "1INCH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x44D618C366D7bC85945Bfc922ACad5B1feF7759A", + "name": "Ancient8", + "symbol": "A8", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/39170/standard/A8_Token-04_200x200.png?1720798300", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x02a24C380dA560E4032Dc6671d8164cfbEEAAE1e", + "name": "Aave", + "symbol": "AAVE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xDDCe42b89215548beCaA160048460747Fe5675bC", + "name": "Arcblock", + "symbol": "ABT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2341/thumb/arcblock.png?1547036543", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xb8A8e137A2dAa25EF1B3577b6598fE8Be66Ecf77", + "name": "Alchemy Pay", + "symbol": "ACH", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/12390/thumb/ACH_%281%29.png?1599691266", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x34424B3352af905e41078a4029b61EDe62BbB32C", + "name": "Across Protocol Token", + "symbol": "ACX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/28161/large/across-200x200.png?1696527165", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x3e1C572d8b069fc2f14ac4f8bdCE6e8eA299A500", + "name": "Ambire AdEx", + "symbol": "ADX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/847/thumb/Ambire_AdEx_Symbol_color.png?1655432540", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xfd38ac2316f6d3631a86065aDb3292f6f15873B5", + "name": "Aergo", + "symbol": "AERGO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4490/thumb/aergo.png?1647696770", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x54FA9210cCB765639b7Fd532f25bCb1060D60F8B", + "name": "Aevo", + "symbol": "AEVO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/35893/standard/aevo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xA4eeF95995F40aD0b3D63a474293Fc7CC681A118", + "name": "agEur", + "symbol": "agEUR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19479/standard/agEUR.png?1696518915", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x14421614587A2A3e9C3Aa3131Fc396aF412721CF", + "name": "Adventure Gold", + "symbol": "AGLD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/18125/thumb/lpgblc4h_400x400.jpg?1630570955", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x5F891E74947b0FC400128E5E85333d7a6cF99b1A", + "name": "AIOZ Network", + "symbol": "AIOZ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14631/thumb/aioz_logo.png?1617413126", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xbf194C82A5Bb9180f9280c1832f886a65Aebdcd6", + "name": "Alchemix", + "symbol": "ALCX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14113/thumb/Alchemix.png?1614409874", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xa3E646211a456e08829C33fcE21cC3DC4c15Bb5c", + "name": "Aleph im", + "symbol": "ALEPH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11676/thumb/Monochram-aleph.png?1608483725", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x2a87dd1e1F849ed88C18565AFDa98e2EEEc73780", + "name": "Alethea Artificial Liquid Intelligence", + "symbol": "ALI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/22062/thumb/alethea-logo-transparent-colored.png?1642748848", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xBb72B8031F590748d8910Aad7e25F8B18860960a", + "name": "My Neighbor Alice", + "symbol": "ALICE", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/14375/thumb/alice_logo.jpg?1615782968", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x44c3E7c49C4Bb6f4f5eCD87E035176dFceBD78d3", + "name": "Alpha Venture DAO", + "symbol": "ALPHA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12738/thumb/AlphaToken_256x256.png?1617160876", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x6D5De04F1a3E0e554B9A15059d03e20cb3589153", + "name": "AltLayer", + "symbol": "ALT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/34608/standard/Logomark_200x200.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x4D6B8ecb576dF9BB4bF6E6764A469a762bBc967F", + "name": "Amp", + "symbol": "AMP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12409/thumb/amp-200x200.png?1599625397", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xf081Fc8E0878D7eBe6ec381E5d7279d6EFf97622", + "name": "Ankr", + "symbol": "ANKR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4324/thumb/U85xTl2.png?1608111978", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x865d184885200B8e86eb2a3Da8b3B4a7d4A31308", + "name": "Aragon", + "symbol": "ANT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/681/thumb/JelZ58cv_400x400.png?1601449653", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xD1b8423FdE5F37464FadE603f80903cB314046cf", + "name": "ApeCoin", + "symbol": "APE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24383/small/apecoin.jpg?1647476455", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xA63122b27308EED0C1D83DD355ADdaA7f678961b", + "name": "API3", + "symbol": "API3", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13256/thumb/api3.jpg?1606751424", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xcDfcE5eb357E8976A80Be84E94a03BA963b9e379", + "name": "Apu Apustaja", + "symbol": "APU", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/35986/large/200x200.png?1710308147", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x5cC70a9DF8E293aFFb14DFCa1e7F851418a4b40d", + "name": "Arbitrum", + "symbol": "ARB", + "decimals": 18, + "logoUrl": "https://arbitrum.foundation/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x59F16BaA7A22f49c32680661e0041A53442Ef089", + "name": "Arkham", + "symbol": "ARKM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/30929/standard/Arkham_Logo_CG.png?1696529771", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xE911A809F87490406AB34fad701aabCA88e30b45", + "name": "ARPA Chain", + "symbol": "ARPA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/8506/thumb/9u0a23XY_400x400.jpg?1559027357", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x4b355De6Ea44711f0353Ed89545705395a30d7Fb", + "name": "ASH", + "symbol": "ASH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15714/thumb/omnPqaTY.png?1622820503", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x1e196D83e2c562de0b1f270Eb72220335bA0ADa7", + "name": "Assemble Protocol", + "symbol": "ASM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11605/thumb/gpvrlkSq_400x400_%281%29.jpg?1591775789", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x7F3F14A49FE5D5009E4e0a09e76cB8468C09Ae56", + "name": "AirSwap", + "symbol": "AST", + "decimals": 4, + "logoUrl": "https://assets.coingecko.com/coins/images/1019/thumb/Airswap.png?1630903484", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xBAAa314d2f5Af29B00867a612F24F816d890C4B2", + "name": "Automata", + "symbol": "ATA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15985/thumb/ATA.jpg?1622535745", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xa249732271cbA6E06Be4ac8B20f0D465FeE183Ab", + "name": "Aethir Token", + "symbol": "ATH", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/36179/large/logogram_circle_dark_green_vb_green_(1).png?1718232706", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x82F90996a4F67Eb388116B3C6F35B6Ea91BeF68E", + "name": "Bounce", + "symbol": "AUCTION", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13860/thumb/1_KtgpRIJzuwfHe0Rl0avP_g.jpeg?1612412025", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x48b8441dE79cEE3604b805093B41028d3c81684B", + "name": "Audius", + "symbol": "AUDIO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12913/thumb/AudiusCoinLogo_2x.png?1603425727", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x38DBf47e2a012a4b83823f15E3F3352A00939999", + "name": "Artverse Token", + "symbol": "AVT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19727/thumb/ewnektoB_400x400.png?1635767094", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xbF678793522638F7439aFE3B94d2D2A3a4cBF2C9", + "name": "Axelar", + "symbol": "AXL", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/27277/large/V-65_xQ1_400x400.jpeg", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xDA63AdA216d2079B54F2047B2FdC2576D188f927", + "name": "Axie Infinity", + "symbol": "AXS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13029/thumb/axie_infinity_logo.png?1604471082", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xc2a564b44b441D03f09f5B6B2b358B4a17388406", + "name": "Badger DAO", + "symbol": "BADGER", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13287/thumb/badger_dao_logo.jpg?1607054976", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x01625E26274Ed828Ac1d47694c97221b34a8ADdF", + "name": "Balancer", + "symbol": "BAL", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xba100000625a3754423978a60c9317c58a424e3D/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xa264F2b88C630f260AbDcAb577eAB7266A8857d5", + "name": "Band Protocol", + "symbol": "BAND", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9545/thumb/band-protocol.png?1568730326", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x4e373C99199773f9D92d32B8c8Bc0C81508ea589", + "name": "Basic Attention Token", + "symbol": "BAT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/677/thumb/basic-attention-token.png?1547034427", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xe5ECB192f1aE5839eD49886F36dFA670f9500824", + "name": "Beam", + "symbol": "BEAM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/32417/standard/chain-logo.png?1698114384", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x604Ff88ADC02325EFb7f93DB3E442dc81D0588E7", + "name": "Biconomy", + "symbol": "BICO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/21061/thumb/biconomy_logo.jpg?1638269749", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x17f3AfE72cAa6b9090801b60607918b6D2Fa7cdc", + "name": "Big Time", + "symbol": "BIGTIME", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/32251/standard/-6136155493475923781_121.jpg?1696998691", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xA4Cb2aaf7503641B441e80fC353e6748fb523A5C", + "name": "BitDAO", + "symbol": "BIT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17627/thumb/rI_YptK8.png?1653983088", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x41f6e69166e81A9583DBc96604B01D2E9B3D706f", + "name": "HarryPotterObamaSonic10Inu", + "symbol": "BITCOIN", + "decimals": 8, + "logoUrl": "https://coin-images.coingecko.com/coins/images/30323/large/hpos10i_logo_casino_night-dexview.png?1696529224", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x942fC6b61686e06fB411cB1bCf5d16DC2b9255eA", + "name": "Blur", + "symbol": "BLUR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/28453/large/blur.png?1670745921", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xe7b3Ca9d9Db06E1867781fd1C5F02E6c8eF471ee", + "name": "Bluzelle", + "symbol": "BLZ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2848/thumb/ColorIcon_3x.png?1622516510", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xf2Cc2D274dA528AB64DA86bE3f8416E5472c5a62", + "name": "Bancor Network Token", + "symbol": "BNT", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xBE8E46422fB7F9Ca9D639B3109492D64BbB41b05", + "name": "Boba Network", + "symbol": "BOBA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/20285/thumb/BOBA.png?1636811576", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x4d5b7e9CCE3Ab81298dA7E1F52b48c9a61Df8972", + "name": "BarnBridge", + "symbol": "BOND", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12811/thumb/barnbridge.jpg?1602728853", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xBbE97f3522101e5B6976cBf77376047097BA837F", + "name": "BONK", + "symbol": "BONK", + "decimals": 5, + "logoUrl": "https://assets.coingecko.com/coins/images/28600/standard/bonk.jpg?1696527587", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x6A4a359C7453F5892392FCb8eAB7A9A100986B71", + "name": "Braintrust", + "symbol": "BTRST", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/18100/thumb/braintrust.PNG?1630475394", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xa4da5c92F44422dFA3E2E309b53d93bbbDa9f9c6", + "name": "Binance USD", + "symbol": "BUSD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x29129fa2e0F35594ca7b362fFA8c80f5f8e4f8E1", + "name": "Coin98", + "symbol": "C98", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17117/thumb/logo.png?1626412904", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xb6A3E8e5715fd4c99EcEDaaAe121bDe4Ab6a1Ef1", + "name": "Coinbase Wrapped BTC", + "symbol": "cbBTC", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/40143/standard/cbbtc.webp", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xEb64b50FeF2A363940369285F86Ae9a68211db59", + "name": "Coinbase Wrapped Staked ETH", + "symbol": "cbETH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/27008/large/cbeth.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x6008F5BaD83742fDbFf5AAc55e3c51b65A8A8D9C", + "name": "Celo native asset (Wormhole)", + "symbol": "CELO", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/wormhole-foundation/wormhole-token-list/main/assets/celo_wh.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x5AD5d6B1AE6761Aab12066b51D21729248035703", + "name": "Celer Network", + "symbol": "CELR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4379/thumb/Celr.png?1554705437", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xAC930Be88cFAc775A937E9291c4234Bf210a4e5b", + "name": "Chromia", + "symbol": "CHR", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/5000/thumb/Chromia.png?1559038018", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xb0C69e24450e29afa8008962052007E08b2396b0", + "name": "Chiliz", + "symbol": "CHZ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/8834/thumb/Chiliz.png?1561970540", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xD7212097f6d6B195a9Bc350b8dCE28a7fA41404C", + "name": "Clover Finance", + "symbol": "CLV", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15278/thumb/clover.png?1645084454", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xdf78e4F0A8279942ca68046476919A90f2288656", + "name": "Compound", + "symbol": "COMP", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xc63612B3e697AEeC61C3Ce9baEc0f9Db32F499C3", + "name": "COTI", + "symbol": "COTI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2962/thumb/Coti.png?1559653863", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x2562DC34c21371613CEF236b321EE63fCC295beC", + "name": "Circuits of Value", + "symbol": "COVAL", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/588/thumb/coval-logo.png?1599493950", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xC3a97c76AA194711E05Ff1d181534090B26D3996", + "name": "CoW Protocol", + "symbol": "COW", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24384/large/CoW-token_logo.png?1719524382", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xF8E7B485CE10D3C7Ac30B8444B98a0cC423dFb57", + "name": "Clearpool", + "symbol": "CPOOL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19252/large/photo_2022-08-31_12.45.02.jpeg?1696518697", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x6C28eeB9E018011d3841f42c5b458713621F90C1", + "name": "Covalent", + "symbol": "CQT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14168/thumb/covalent-cqt.png?1624545218", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x73c63A80Ec77BFe31eEc6663828C4beaA30dE818", + "name": "Cronos", + "symbol": "CRO", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/7310/thumb/oCw2s3GI_400x400.jpeg?1645172042", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x7e7784f13029c7C4BF4746112B1A503818B0D066", + "name": "Crypterium", + "symbol": "CRPT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1901/thumb/crypt.png?1547036205", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xAC73671a1762FE835208Fb93b7aE7490d1c2cCb3", + "name": "Curve DAO Token", + "symbol": "CRV", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xD533a949740bb3306d119CC777fa900bA034cd52/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xa7073F530856cD32c2037150dd9763B9BAaED2C5", + "name": "Cartesi", + "symbol": "CTSI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x36fA435F6def83cbB7a0706d035C9eA062fCb619", + "name": "Cryptex Finance", + "symbol": "CTX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14932/thumb/glossy_icon_-_C200px.png?1619073171", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xE60e9b2E68297d5DF6B383fEe787B7fB92c2F8aF", + "name": "Somnium Space CUBEs", + "symbol": "CUBE", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/10687/thumb/CUBE_icon.png?1617026861", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x35C458aD1e3e68d2717C8349b985384Be85a01Ed", + "name": "Civic", + "symbol": "CVC", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/788/thumb/civic.png?1547034556", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x1C6789F30e7E335c2Eca2c75EC193aDBF0087Ea5", + "name": "Convex Finance", + "symbol": "CVX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15585/thumb/convex.png?1621256328", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x8E29E12B46FeE20E034fE1e812bc12EFf14E5A09", + "name": "Covalent X Token", + "symbol": "CXT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/39177/large/CXT_Ticker.png?1720829918", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x20CAb320A855b39F724131C69424240519573f81", + "name": "Dai Stablecoin", + "symbol": "DAI", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png", + "priceUsd": "0.9976393847564363" + }, + { + "chainId": 130, + "address": "0x2ef0775A19d1bc2258653fc5529F8f8490288086", + "name": "Mines of Dalarnia", + "symbol": "DAR", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/19837/thumb/dar.png?1636014223", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x91ED4bb192e3461E45575730508525083A270265", + "name": "DerivaDAO", + "symbol": "DDX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13453/thumb/ddx_logo.png?1608741641", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x45a4f750d806498A4c7f7B5267815aaC328e874C", + "name": "Dent", + "symbol": "DENT", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/1152/thumb/gLCEA2G.png?1604543239", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x17C38207334011a131b0Acf200E35Cd81723cddd", + "name": "DexTools", + "symbol": "DEXT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11603/thumb/dext.png?1605790188", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x4bdc8553cf14EEBCD489cD1d75b7FF463f9543c2", + "name": "DIA", + "symbol": "DIA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11955/thumb/image.png?1646041751", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x0eb07cE7a28FF84DF132fb5ee5F56Aabc1b9E545", + "name": "district0x", + "symbol": "DNT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/849/thumb/district0x.png?1547223762", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x12E96C2BFEA6E835CF8Dd38a5834fa61Cf723736", + "name": "Dogecoin", + "symbol": "DOGE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/5/standard/dogecoin.png?1696501409", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xE274f564c37aE15fd2570D544102eD4ACd2f84f1", + "name": "DeFi Pulse Index", + "symbol": "DPI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12465/thumb/defi_pulse_index_set.png?1600051053", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x56aF109D597eb0a0F79ebCD0786Dd88C38EA9Ee7", + "name": "Drep", + "symbol": "DREP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14578/thumb/KotgsCgS_400x400.jpg?1617094445", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x601b11907EAa8d3785C0b10b41C3a7315faeB82c", + "name": "dYdX", + "symbol": "DYDX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17500/thumb/hjnIm9bV.jpg?1628009360", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xBdaD8E37a9600F0A35976fE61608a4C89D598610", + "name": "DeFi Yield Protocol", + "symbol": "DYP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13480/thumb/DYP_Logo_Symbol-8.png?1655809066", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xc89ab9B82610BB9b748F6757b8F3ac59d016C47D", + "name": "EigenLayer", + "symbol": "EIGEN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/37441/large/eigen.jpg?1728023974", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x24aBc32215354Ba3eD224bfa6312E31dD8E8c1ab", + "name": "Elastos", + "symbol": "ELA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2780/thumb/Elastos.png?1597048112", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x91441fE1415B00bEA8930A4354Fe00c426C1DE05", + "name": "Dogelon Mars", + "symbol": "ELON", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14962/thumb/6GxcPRo3_400x400.jpg?1619157413", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x9116E70d613860D349495d9Ef8e2AE1cA6cBD2dd", + "name": "Ethena", + "symbol": "ENA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/36530/standard/ethena.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x9A0D1b7594CAAF0A9e4687cAc9fF4E0B84a6d0A6", + "name": "Enjin Coin", + "symbol": "ENJ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1102/thumb/enjin-coin-logo.png?1547035078", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x80756FAf1e7Fec5678bf505670eF176AB5F0383a", + "name": "Ethereum Name Service", + "symbol": "ENS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19785/thumb/acatxTm8_400x400.jpg?1635850140", + "priceUsd": "35.297130407667666" + }, + { + "chainId": 130, + "address": "0x5E5903C236E6873EB8400C3d1979271Fa93cdB03", + "name": "Ethernity Chain", + "symbol": "ERN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14238/thumb/LOGO_HIGH_QUALITY.png?1647831402", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xF8740269F121327D03ff77BeD03a9A3258880821", + "name": "Ether.fi", + "symbol": "ETHFI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/35958/standard/etherfi.jpeg", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x6319F47719b6713b1624C1b3A8e2DBf15b5D03FE", + "name": "Euler", + "symbol": "EUL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/26149/thumb/YCvKDfl8_400x400.jpeg?1656041509", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x72f34BC403a005A9Be390762EAa46ED42813B0a8", + "name": "Euro Coin", + "symbol": "EURC", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/26045/thumb/euro-coin.png?1655394420", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xEc42461D9BbDF4eFB6481099253bBB7324D7d72d", + "name": "Quantoz EURQ", + "symbol": "EURQ", + "decimals": 6, + "logoUrl": "https://coin-images.coingecko.com/coins/images/51853/large/EURQ_1000px_Color.png?1732071269", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x7A1ef7fD6E0d708295D8FD0C30Fd437d9C36FB5f", + "name": "StablR Euro", + "symbol": "EURR", + "decimals": 6, + "logoUrl": "https://coin-images.coingecko.com/coins/images/53720/large/stablreuro-logo.png?1737125898", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x472E8be16Cc9823b9f6a73A34EA55c0c31ee825F", + "name": "Harvest Finance", + "symbol": "FARM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12304/thumb/Harvest.png?1613016180", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x45343279DefDAd803d81C06fBCf87936DDD7DFE7", + "name": "Fetch ai", + "symbol": "FET", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/5681/thumb/Fetch.jpg?1572098136", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xec9Be303f204864145CCC193aEb21B5fa10764A6", + "name": "Stafi", + "symbol": "FIS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12423/thumb/stafi_logo.jpg?1599730991", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x1b3EC249dc44a64bF5Cb8Afdd70e30c26c51fA81", + "name": "FLOKI", + "symbol": "FLOKI", + "decimals": 9, + "logoUrl": "https://assets.coingecko.com/coins/images/16746/standard/PNG_image.png?1696516318", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xB20fD6fD28e1430f98a8C1e9A83C88E5D87D94e5", + "name": "Forta", + "symbol": "FORT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/25060/thumb/Forta_lgo_%281%29.png?1655353696", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xFa004fa2ad8Ef993C2B0412baB776b182220F12e", + "name": "Ampleforth Governance Token", + "symbol": "FORTH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14917/thumb/photo_2021-04-22_00.00.03.jpeg?1619020835", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xe0BB1924C17b39B71758F49a00D7c0363B7a318E", + "name": "ShapeShift FOX Token", + "symbol": "FOX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9988/thumb/FOX.png?1574330622", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x8c7879bf25D678D9949F305857bD4437d74132B9", + "name": "Frax", + "symbol": "FRAX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13422/thumb/frax_logo.png?1608476506", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xe99235A02958637a5e01575297fBBa3790dC7F0e", + "name": "Fantom", + "symbol": "FTM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4001/thumb/Fantom.png?1558015016", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x6F32725F82Bbb06FFdC04974db437fec1d7af1Af", + "name": "Function X", + "symbol": "FX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/8186/thumb/47271330_590071468072434_707260356350705664_n.jpg?1556096683", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x79301DF2117C7F56859fD01b28bBAA61062021D6", + "name": "Frax Share", + "symbol": "FXS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13423/thumb/frax_share.png?1608478989", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x481cB2C560fc3351833b582b92b965626fd8803C", + "name": "Gravity", + "symbol": "G", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/39200/large/gravity.jpg?1721020647", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x70b2b785061d4c91C76CF87692f85B5c443d8675", + "name": "Galxe", + "symbol": "GAL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24530/thumb/GAL-Token-Icon.png?1651483533", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x31A71801291774d267615f74b3a44FCEB560FAc9", + "name": "GALA", + "symbol": "GALA", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/12493/standard/GALA-COINGECKO.png?1696512310", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x0328A0255866706547B79072DEE54976b157d3D0", + "name": "Goldfinch", + "symbol": "GFI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19081/thumb/GOLDFINCH.png?1634369662", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x4aE5712A153fDfDE81C305fF7f2E4e59840aD24B", + "name": "Aavegotchi", + "symbol": "GHST", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12467/thumb/ghst_200.png?1600750321", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x04b747f478AE09AC797d026C8402f409E2C9f2b9", + "name": "Golem", + "symbol": "GLM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/542/thumb/Golem_Submark_Positive_RGB.png?1606392013", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xC4c6c3A3043Ad5ECe5c91290630A7735e125a938", + "name": "Gnosis Token", + "symbol": "GNO", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6810e776880C02933D47DB1b9fc05908e5386b96/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x6E74EA6546e1f21Abf581b59114f2Bf5d3683f48", + "name": "Gods Unchained", + "symbol": "GODS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17139/thumb/10631.png?1635718182", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xBb2272Ffc0Ef8F439373aDffD45c3591B3204D71", + "name": "The Graph", + "symbol": "GRT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13397/thumb/Graph_Token.png?1608145566", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x592620d454a10c47274dBfe3BD922b9a8fE5cf48", + "name": "Gitcoin", + "symbol": "GTC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15810/thumb/gitcoin.png?1621992929", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xEbA12eC786Cdc21b4bd5ba601B595b6A5C0920a9", + "name": "Gemini Dollar", + "symbol": "GUSD", + "decimals": 2, + "logoUrl": "https://assets.coingecko.com/coins/images/5992/thumb/gemini-dollar-gusd.png?1536745278", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xad173F5B5FE39DD1183a0d3C49C57629A574c36F", + "name": "GYEN", + "symbol": "GYEN", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/14191/thumb/icon_gyen_200_200.png?1614843343", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x656104f2028BbFD7144C8f71Fa15daaA8c34A28b", + "name": "Hashflow", + "symbol": "HFT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/26136/large/hashflow-icon-cmc.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x99F64C3Db98a4870eFf637315d5C86dcb1374879", + "name": "Highstreet", + "symbol": "HIGH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/18973/thumb/logosq200200Coingecko.png?1634090470", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xc32C0c5a52F36D244C552E45C485cBceaf385B36", + "name": "HOPR", + "symbol": "HOPR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14061/thumb/Shared_HOPR_logo_512px.png?1614073468", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x4eA052BcAeE7d7ef2E3D61D601e878A560eaBe8e", + "name": "IDEX", + "symbol": "IDEX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2565/thumb/logomark-purple-286x286.png?1638362736", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xa76195FA77304Bba4cD8946198f5a90E42F3E51F", + "name": "Illuvium", + "symbol": "ILV", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14468/large/ILV.JPG", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xc4Fc8cF76883094404DDb875d2AF15D1F5AA8053", + "name": "Immutable X", + "symbol": "IMX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17233/thumb/imx.png?1636691817", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xa5Afe7646f07d2C41AA82Bb6AE09e99E121e39B7", + "name": "Index Cooperative", + "symbol": "INDEX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12729/thumb/index.png?1634894321", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x9361cA28625E12C7f088523B274A25059A89f9F8", + "name": "Injective", + "symbol": "INJ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12882/thumb/Secondary_Symbol.png?1628233237", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xD326ACaB8799fb44C3A5B7f7eFbAaB5f9F7b54fb", + "name": "Inverse Finance", + "symbol": "INV", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14205/thumb/inverse_finance.jpg?1614921871", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xD749094Bc62615f0c8645467e241b71Ae2B6843F", + "name": "IoTeX", + "symbol": "IOTX", + "decimals": 18, + "logoUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/2777.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x428c2B7Fa7a7821891fb529BAE4d80a71d5c61A8", + "name": "Geojam", + "symbol": "JAM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24648/thumb/ey40AzBN_400x400.jpg?1648507272", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x8EF0686F380dD07f3e2121831839371922720708", + "name": "JasmyCoin", + "symbol": "JASMY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13876/thumb/JASMY200x200.jpg?1612473259", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x781CC305fCBFe7cde376C9Ef5469d5a7E5CaB8b2", + "name": "Jupiter", + "symbol": "JUP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/10351/thumb/logo512.png?1632480932", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xbe51A5e8FA434F09663e8fB4CCe79d0B2381Afad", + "name": "Jupiter", + "symbol": "JUP", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/34188/standard/jup.png?1704266489", + "priceUsd": "0.405015" + }, + { + "chainId": 130, + "address": "0x05DBd720fc26F732c8d42Ea89BD7F442EA6AFE80", + "name": "Keep Network", + "symbol": "KEEP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3373/thumb/IuNzUb5b_400x400.jpg?1589526336", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x68Cea24F675e4F25584607F6c9feFb353f1bBfDc", + "name": "SelfKey", + "symbol": "KEY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2034/thumb/selfkey.png?1548608934", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xB0E4Ad2dFe3754e4a2443A7a828Eda5bB7Cd2284", + "name": "Kyber Network Crystal", + "symbol": "KNC", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdd974D5C2e2928deA5F71b9825b8b646686BD200/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x9C41547e404942C173E28bB2B6abE4cf5fad6A74", + "name": "Keep3rV1", + "symbol": "KP3R", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12966/thumb/kp3r_logo.jpg?1607057458", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x14CFFAD448AeB0876c56B7aa28999C9a4f002943", + "name": "KRYLL", + "symbol": "KRL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2807/thumb/krl.png?1547036979", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x2206cdcC9B94fF7dB7A9eAbeC77b5cE430258681", + "name": "Kujira", + "symbol": "KUJI", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/20685/standard/kuji-200x200.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x1201209f55634bdDb67034efE4e8aA4D1B7B482C", + "name": "Layer3", + "symbol": "L3", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/37768/large/Square.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xb34b3DE63D22ffC90419c1a439de6C7d46687782", + "name": "LCX", + "symbol": "LCX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9985/thumb/zRPSu_0o_400x400.jpg?1574327008", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x68A6dbc7214a0F2b0d875963663F1613814E8829", + "name": "Lido DAO", + "symbol": "LDO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13573/thumb/Lido_DAO.png?1609873644", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x5a53B6D19D8EDCb7923F0D840EeBB3f09BBeEfB7", + "name": "ChainLink Token", + "symbol": "LINK", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png", + "priceUsd": "17.244063485784068" + }, + { + "chainId": 130, + "address": "0x68648F52B85407806bC1d349B745D13C91be0fDf", + "name": "Litentry", + "symbol": "LIT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13825/large/logo_200x200.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x1D1BFCFC6ae6FE045f151C7e589fB241AAC89733", + "name": "League of Kingdoms", + "symbol": "LOKA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/22572/thumb/loka_64pix.png?1642643271", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xc68992e0514968BfbA3Dad201fef91f6009f523c", + "name": "Loom Network", + "symbol": "LOOM", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x11c6B34caDC550B65A9666497d7FCb39f35B73E3", + "name": "Livepeer", + "symbol": "LPT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/7137/thumb/logo-circle-green.png?1619593365", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x0176B38b7767451b1B682236eCe2fae853C71a60", + "name": "Liquity", + "symbol": "LQTY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14665/thumb/200-lqty-icon.png?1617631180", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xA2af802b95D7e20167e5aeaC7Fe8fDf4a8aB158A", + "name": "LoopringCoin V2", + "symbol": "LRC", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xD7eb7348Ba44c5A2f9f1D1d3534623230c7bee3F", + "name": "BLOCKLORDS", + "symbol": "LRDS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/34775/standard/LRDS_PNG.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xc13C1Aa97ef67a1eBd56830323B04C3A75df1903", + "name": "Lisk", + "symbol": "LSK", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/385/large/Lisk_logo.png?1722338450", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xf81B7485B4cB59645F74528D702c7f8CD72577FB", + "name": "Liquity USD", + "symbol": "LUSD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14666/thumb/Group_3.png?1617631327", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x276361c863903751771e9DabA6dDfaAf00FE358b", + "name": "Decentraland", + "symbol": "MANA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/878/thumb/decentraland-mana.png?1550108745", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xC42B642F5010a2A3bD3CA2396Fe6f2e21B9512C4", + "name": "Mask Network", + "symbol": "MASK", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14051/thumb/Mask_Network.jpg?1614050316", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xB999b66186d7a48BF0Eb5d22f4E7053A99eD2C97", + "name": "MATH", + "symbol": "MATH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11335/thumb/2020-05-19-token-200.png?1589940590", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xF6AC97B05B3bC92f829c7584b25839906507176b", + "name": "Polygon", + "symbol": "MATIC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x460ec1C67e1614Bf1feAb84b98795BAE2d657399", + "name": "Merit Circle", + "symbol": "MC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19304/thumb/Db4XqML.png?1634972154", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x68619Bc0C709FB63555Fe988ed14e78f7E6ACc40", + "name": "Moss Carbon Credit", + "symbol": "MCO2", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14414/thumb/ENtxnThA_400x400.jpg?1615948522", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xB29FddC20D5e4bacE9F54c1d9237953331BFeFF4", + "name": "Measurable Data Token", + "symbol": "MDT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2441/thumb/mdt_logo.png?1569813574", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x397E34AFF8bFc8Ec14aa78F378074F6d8E3E7d06", + "name": "Memecoin", + "symbol": "MEME", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/32528/large/memecoin_(2).png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xBfBa2A8745e5C85544DB7C8824C6962aB3A8f102", + "name": "Metis", + "symbol": "METIS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15595/thumb/metis.jpeg?1660285312", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x397C1f55FefF63C8947624b0d457a2CA3e3602ab", + "name": "Magic Internet Money", + "symbol": "MIM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/16786/thumb/mimlogopng.png?1624979612", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x5FE989EaB3021d7e742099d05a7937bA4A72D717", + "name": "Mirror Protocol", + "symbol": "MIR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13295/thumb/mirror_logo_transparent.png?1611554658", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xf7A581f6e26EEa790225d76Af8821EA34Dc3c117", + "name": "Melon", + "symbol": "MLN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/605/thumb/melon.png?1547034295", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x58d68e179864605fEA06EAADF1185c6e78921Ebd", + "name": "Mog Coin", + "symbol": "MOG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/31059/large/MOG_LOGO_200x200.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xAe6065FB0244A68036C82deC9a8dE5501c7A1087", + "name": "Monavale", + "symbol": "MONA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13298/thumb/monavale_logo.jpg?1607232721", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xaa2109f14Bb155766cBA9E7fa8B8D4bF0ff19949", + "name": "Movement", + "symbol": "MOVE", + "decimals": 8, + "logoUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/32452.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x587e0E022b074015F4e81eCa489c0C41d752A219", + "name": "Maple", + "symbol": "MPL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14097/thumb/photo_2021-05-03_14.20.41.jpeg?1620022863", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x71d69d07914d087f1C3536F7A5006a256CfAd9Ea", + "name": "Metal", + "symbol": "MTL", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/763/thumb/Metal.png?1592195010", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x1C3a8fB65Ab82D73e26B6403bf505B99d82b4701", + "name": "Multichain", + "symbol": "MULTI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/22087/thumb/1_Wyot-SDGZuxbjdkaOeT2-A.png?1640764238", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x10F109379E231d5c294ee6A5f9Abb2F8b40A8Dd1", + "name": "mStable USD", + "symbol": "MUSD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11576/thumb/mStable_USD.png?1595591803", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xe3d92FB06a4EEbaC5879D3C1073e0eAB81D5f345", + "name": "Muse DAO", + "symbol": "MUSE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13230/thumb/muse_logo.png?1606460453", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xD6ec6A24d5365A1811B05099f8D353c0Ff182974", + "name": "GensoKishi Metaverse", + "symbol": "MV", + "decimals": 18, + "logoUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/17704.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xCF7c45Ccc1327ac1E9Cb9E098898c59402727794", + "name": "MXC", + "symbol": "MXC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4604/thumb/mxc.png?1655534336", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x328Ed7736871F863C8216Ca6CbB6f29B795032Df", + "name": "PolySwarm", + "symbol": "NCT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2843/thumb/ImcYCVfX_400x400.jpg?1628519767", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xc1C06527E810C4A198D8C5d35e1dDBc987696276", + "name": "Neiro", + "symbol": "Neiro", + "decimals": 9, + "logoUrl": "https://coin-images.coingecko.com/coins/images/39488/large/neiro.jpg?1731449567", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x75b93cED9627Cd172912304Fb79Cd3e7336BaF62", + "name": "NKN", + "symbol": "NKN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3375/thumb/nkn.png?1548329212", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x931e587542b8603EA3C6420dD8d3b22eDbdA20FC", + "name": "Numeraire", + "symbol": "NMR", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x2AEB5256de25ECed47797b82d2F5C404AACEA6b9", + "name": "NuCypher", + "symbol": "NU", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3318/thumb/photo1198982838879365035.jpg?1547037916", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x652293F4e9b0ef61C52a78D6615D9f5f3cD79208", + "name": "Ocean Protocol", + "symbol": "OCEAN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3687/thumb/ocean-protocol-logo.jpg?1547038686", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xa60CE8f7ec6A091535b4708569B39DF5eE18c880", + "name": "Origin Protocol", + "symbol": "OGN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3296/thumb/op.jpg?1547037878", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x5949b9200dF1e77878dB3D061e43cF878Ee37383", + "name": "OMG Network", + "symbol": "OMG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/776/thumb/OMG_Network.jpg?1591167168", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xf5614D20c13D5BF2F9e640f00B7B2B76959Eb0E3", + "name": "Omni Network", + "symbol": "OMNI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/36465/standard/Symbol-Color.png?1711511095", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xaD0bae21db0b471dFfC6f8F9EEacFe9A85321557", + "name": "Ondo Finance", + "symbol": "ONDO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/26580/standard/ONDO.png?1696525656", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xCF2050ebC80B74370C1C2B71bDB635d11be3E8c0", + "name": "ORCA Alliance", + "symbol": "ORCA", + "decimals": 18, + "logoUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/5183.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x3C5319013FD75976F0f13b0bc0852537B6eaF396", + "name": "Orion Protocol", + "symbol": "ORN", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/11841/thumb/orion_logo.png?1594943318", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x9775C2b4f245248dE5596252Ac69311152B98042", + "name": "Orchid", + "symbol": "OXT", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x4575f41308EC1483f3d399aa9a2826d74Da13Deb/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x3614c8d98Bf905AbE075BfA289231bbc0D292327", + "name": "PayperEx", + "symbol": "PAX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1601/thumb/pax.png?1547035800", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x89f7C0870794103744C8042630CC1C846a858E57", + "name": "PAX Gold", + "symbol": "PAXG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9519/thumb/paxg.PNG?1568542565", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xeC37cdfC9a692b3cCd5c85696D14aaA31E75d6aC", + "name": "PlayDapp", + "symbol": "PDA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14316/standard/PDA-symbol.png?1710234068", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xD9b5DA95B3D97c3E9872102fDb47d4c09074952B", + "name": "Pepe", + "symbol": "PEPE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/29850/large/pepe-token.jpeg?1682922725", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x5944D2728d5fea7D1F4AA4958E3aEbb3CCFEc7D5", + "name": "Perpetual Protocol", + "symbol": "PERP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xd0F77df9a8f0e855F910361f5f59958118d064c6", + "name": "Pirate Nation", + "symbol": "PIRATE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/38524/standard/_Pirate_Transparent_200x200.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x5441619a9754Aee0665c939743cf7611abB6F6C7", + "name": "Pluton", + "symbol": "PLU", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1241/thumb/pluton.png?1548331624", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xF6A49aEdbD7861DeD0DA2BE1f21C6954E5682E95", + "name": "Polygon Ecosystem Token", + "symbol": "POL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/32440/large/polygon.png?1698233684", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x82a98121eaf30b0E135b08d4208c837Cdc306503", + "name": "Polkastarter", + "symbol": "POLS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12648/thumb/polkastarter.png?1609813702", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x2f5cfdC89fb96f2cf6c0FB1Ca6e3501Dd538D863", + "name": "Polymath", + "symbol": "POLY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2784/thumb/inKkF01.png?1605007034", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xA2a36541c5a54bd2815985418105091B4D4782d5", + "name": "Marlin", + "symbol": "POND", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/8903/thumb/POND_200x200.png?1622515451", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x562E588471cA0e710b2b1217867FFb2E0F2a5642", + "name": "Portal", + "symbol": "PORTAL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/35436/standard/portal.jpeg", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xf265af514762286A63d015FeE382B90edfFa6bff", + "name": "Power Ledger", + "symbol": "POWR", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/1104/thumb/power-ledger.png?1547035082", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xD17D5f0DA4200bBfd3D6626AC6aEA2eccbf9fEE0", + "name": "Prime", + "symbol": "PRIME", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/29053/large/PRIMELOGOOO.png?1676976222", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xC6Fbf362a12804FEca22000f37DB5EFC1F41A7c9", + "name": "Propy", + "symbol": "PRO", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/869/thumb/propy.png?1548332100", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xc7B7dcF3c6CAcAAc13F92c9173f9A0060ABf3def", + "name": "PARSIQ", + "symbol": "PRQ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11973/thumb/DsNgK0O.png?1596590280", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x13FE2c4504f3AA18708561250e2F20E4E7D7CAa2", + "name": "pSTAKE Finance", + "symbol": "PSTAKE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/23931/thumb/PSTAKE_Dark.png?1645709930", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xAdf70dc4AaeFbC6D1E7A6cF0B02b0F2138b560d2", + "name": "Puffer Finance", + "symbol": "PUFFER", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/50630/large/puffer.jpg?1728545297", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x0D2f98904D88909072eA6e61105CBBf78e6207c5", + "name": "PayPal USD", + "symbol": "PYUSD", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/31212/large/PYUSD_Logo_%282%29.png?1691458314", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x3a8723f2929F370c61EaC583d6652e5C98C360d4", + "name": "Quant", + "symbol": "QNT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3370/thumb/5ZOu7brX_400x400.jpg?1612437252", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x006254C4664C678e64c3265da28304cc8c1068b8", + "name": "Qredo", + "symbol": "QRDO", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/17541/thumb/qrdo.png?1630637735", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xb019a038eaDCB2F96321D236F6633C8d6Bb5eAbB", + "name": "Quantstamp", + "symbol": "QSP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1219/thumb/0_E0kZjb4dG4hUnoDD_.png?1604815917", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xD815958F92E6aBe63437BCe166E97027f8E6caC2", + "name": "Quickswap", + "symbol": "QUICK", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13970/thumb/1_pOU6pBMEmiL-ZJVb0CYRjQ.png?1613386659", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x3F9A30c86DC7F0c657eA17d52Efe09Eff08a1a45", + "name": "Radicle", + "symbol": "RAD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14013/thumb/radicle.png?1614402918", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x6164A78F7B2aC49cf9b76c49e5B6909e89f34a66", + "name": "Rai Reflex Index", + "symbol": "RAI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14004/thumb/RAI-logo-coin.png?1613592334", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xe8a0078aA52ac7e93aE43818DdD64591E025BB6F", + "name": "SuperRare", + "symbol": "RARE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17753/thumb/RARE.jpg?1629220534", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x16F01392Ed7fC6F3C345CF544cf1172103C8561C", + "name": "Rarible", + "symbol": "RARI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11845/thumb/Rari.png?1594946953", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x29EA5682024c8C62Cd8BDf691C4f0c5D66B403E3", + "name": "Rubic", + "symbol": "RBC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12629/thumb/200x200.png?1607952509", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x75B2dBb2a7C70073133E42F64366a986c841cd3e", + "name": "Ribbon Finance", + "symbol": "RBN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15823/thumb/RBN_64x64.png?1633529723", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x560603E0bFC941063D1375Ec4E3f9FE38261617E", + "name": "Republic Token", + "symbol": "REN", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x408e41876cCCDC0F92210600ef50372656052a38/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x097ca3FC389697080C84148C455Ca839b2816Fc4", + "name": "Reputation Augur v1", + "symbol": "REP", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1985365e9f78359a9B6AD760e32412f4a445E862/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xE86B1E5613a5761D005a2D00D8a1B4ad1e72A8c4", + "name": "Reputation Augur v2", + "symbol": "REPv2", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x221657776846890989a759BA2973e427DfF5C9bB/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x9FcC3133779F2039c29908c915b6EFaE9d8663Cd", + "name": "Request", + "symbol": "REQ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1031/thumb/Request_icon_green.png?1643250951", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xc14a68015fA6396eF97B57839da544910f9Ca657", + "name": "REVV", + "symbol": "REVV", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12373/thumb/REVV_TOKEN_Refined_2021_%281%29.png?1627652390", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x2178f07c1d585C39272CAf69A72beF08aAD6c9AB", + "name": "Renzo", + "symbol": "REZ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/37327/standard/renzo_200x200.png?1714025012", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x8c9606001CF1787CEb80E03DEF3F9BaF946CF284", + "name": "Rari Governance Token", + "symbol": "RGT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12900/thumb/Rari_Logo_Transparent.png?1613978014", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x538fB2719135740b8877607217Dc391FB3347ACb", + "name": "iExec RLC", + "symbol": "RLC", + "decimals": 9, + "logoUrl": "https://assets.coingecko.com/coins/images/646/thumb/pL1VuXm.png?1604543202", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x7Ad899b7C793743fDE692d982F190f443F88c889", + "name": "Rally", + "symbol": "RLY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12843/thumb/image.png?1611212077", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x965C6DeBFa700F53a38d42DbaeD922c58d649868", + "name": "Render Token", + "symbol": "RNDR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11636/thumb/rndr.png?1638840934", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x682B2f07e61022A80Ac2753448f7D95E9de41D99", + "name": "Rook", + "symbol": "ROOK", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13005/thumb/keeper_dao_logo.jpg?1604316506", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x993A565A1E6219951323cA3c34Cee0A3b1889066", + "name": "Reserve Rights", + "symbol": "RSR", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/8365/large/RSR_Blue_Circle_1000.png?1721777856", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x47B72717E48Da346C3F1ED1311c8DCDe10EfD888", + "name": "Safe", + "symbol": "SAFE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/27032/standard/Artboard_1_copy_8circle-1.png?1696526084", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x6A654A2ec95fB988Ea37746dBCca10772CAf25CA", + "name": "The Sandbox", + "symbol": "SAND", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12129/thumb/sandbox_logo.jpg?1597397942", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x7ccc67C7b232aa6417d9422e90D91ec4b32d72E5", + "name": "Stader", + "symbol": "SD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/20658/standard/SD_Token_Logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xaa571d01057cdF477D73433D36D86fCb5664158e", + "name": "Shiba Inu", + "symbol": "SHIB", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11939/thumb/shiba.png?1622619446", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x45Bda7bA10DaC525a86DBEaB3135701A66024F2F", + "name": "Shping", + "symbol": "SHPING", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2588/thumb/r_yabKKi_400x400.jpg?1639470164", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x486Bbb6f250343AdB4782F50Dd09766f8aD20c01", + "name": "SKALE", + "symbol": "SKL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13245/thumb/SKALE_token_300x300.png?1606789574", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x5A6058002d0d336e5E8860652e7054a6d07074E4", + "name": "SKY Governance Token", + "symbol": "SKY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/39925/large/sky.jpg?1724827980", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xbD2DD310FECBFb1111fC3262F3a97bA696cb03B3", + "name": "Smooth Love Potion", + "symbol": "SLP", + "decimals": 0, + "logoUrl": "https://assets.coingecko.com/coins/images/10366/thumb/SLP.png?1578640057", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x914f7CE2B080B2186159C2213B1e193E265aBF5F", + "name": "Status", + "symbol": "SNT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/779/thumb/status.png?1548610778", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x022D952aBCc6C8271F26e59e37A65dC359E6bc88", + "name": "Synthetix Network Token", + "symbol": "SNX", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x5e03C123D829505F4DEa87cf679F77c9dC4627ab", + "name": "Unisocks", + "symbol": "SOCKS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/10717/thumb/qFrcoiM.png?1582525244", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x4Ff3E944D5Cb54f6f4A1dd035782BE59c3d054FE", + "name": "SOL Wormhole ", + "symbol": "SOL", + "decimals": 9, + "logoUrl": "https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xbdE8A5331E8Ac4831cf8ea9e42e229219EafaB97", + "name": "Solana", + "symbol": "SOL", + "decimals": 9, + "logoUrl": "https://coin-images.coingecko.com/coins/images/54680/large/base.png?1749023388", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x739316C7bc4A39Eb39dcFa1b181b64abc17fEF7F", + "name": "Spell Token", + "symbol": "SPELL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15861/thumb/abracadabra-3.png?1622544862", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x51A7b9a11f10D04C16306D90dc4EC22b036DD629", + "name": "SPX6900", + "symbol": "SPX", + "decimals": 8, + "logoUrl": "https://coin-images.coingecko.com/coins/images/31401/large/sticker_(1).jpg?1702371083", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x77c8A8E1dd3b5270d3Ab589543e9A83319373135", + "name": "Stargate Finance", + "symbol": "STG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24413/thumb/STG_LOGO.png?1647654518", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xf13B5B21555092882e69b22282DAf891c9951835", + "name": "Storj Token", + "symbol": "STORJ", + "decimals": 8, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x09f705405677970E509d606348D4635D2332c72e", + "name": "Starknet", + "symbol": "STRK", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/26433/standard/starknet.png?1696525507", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xEf86E70E534E02AADEAE95b843973d4AcacCeA22", + "name": "Stox", + "symbol": "STX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1230/thumb/stox-token.png?1547035256", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xc05B416738DDEBd14D5A9B790a6e1ce782176525", + "name": "SUKU", + "symbol": "SUKU", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11969/thumb/UmfW5S6f_400x400.jpg?1596602238", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x0c288302629Fc22504D59Ddf8fbf8AA92bD86D3D", + "name": "SuperFarm", + "symbol": "SUPER", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14040/thumb/6YPdWn6.png?1613975899", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x7251d204c2e867b31096D5c7091298239B3A6a0F", + "name": "Synth sUSD", + "symbol": "sUSD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/5013/thumb/sUSD.png?1616150765", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x2982Be2D0c6ae4A7D5BC1c8fe7B630E3BDfb3ce5", + "name": "Sushi", + "symbol": "SUSHI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xa8015cbc9f7c58788BA00854c330F027028A5870", + "name": "Swell", + "symbol": "SWELL", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/28777/large/swell1.png?1727899715", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x0610cDF9856b8825213672981056CD4945Af1616", + "name": "SWFTCOIN", + "symbol": "SWFTC", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/2346/thumb/SWFTCoin.jpg?1618392022", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xDcA295E850666753c6332D6B0E0445B09785c2E1", + "name": "Swipe", + "symbol": "SXP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9368/thumb/swipe.png?1566792311", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x1BAAc1979527A38F367c6f89bE081aBfcFFCF85E", + "name": "Sylo", + "symbol": "SYLO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/6430/thumb/SYLO.svg?1589527756", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xCeb1F5671C47cee096C3B40353863b6781888A48", + "name": "Synapse", + "symbol": "SYN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/18024/thumb/syn.png?1635002049", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x8f7F997ba304f426E3138999919c23f68cD6FA96", + "name": "Syrup Token", + "symbol": "SYRUP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/51232/standard/IMG_7420.png?1730831572", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x8F43Ab8648F1a3BAEea3782Ba5f562a148f2Ad54", + "name": "Threshold Network", + "symbol": "T", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/22228/thumb/nFPNiSbL_400x400.jpg?1641220340", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xAd497996Dc33DC8E8e552824CcEe199420BC7814", + "name": "tBTC", + "symbol": "tBTC", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/uniswap/assets/master/blockchains/ethereum/assets/0x18084fbA666a33d37592fA2633fD49a74DD93a88/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xD9Cbd701bbEA8e9Aaee7d82aa60748451eDa749c", + "name": "ChronoTech", + "symbol": "TIME", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/604/thumb/time-32x32.png?1627130666", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xd649b9AD2104418B5b032a5899fBcd54a9a46c68", + "name": "Alien Worlds", + "symbol": "TLM", + "decimals": 4, + "logoUrl": "https://assets.coingecko.com/coins/images/14676/thumb/kY-C4o7RThfWrDQsLCAG4q4clZhBDDfJQVhWUEKxXAzyQYMj4Jmq1zmFwpRqxhAJFPOa0AsW_PTSshoPuMnXNwq3rU7Imp15QimXTjlXMx0nC088mt1rIwRs75GnLLugWjSllxgzvQ9YrP4tBgclK4_rb17hjnusGj_c0u2fx0AvVokjSNB-v2poTj0xT9BZRCbzRE3-lF1.jpg?1617700061", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x5eD5DA180bB125f229AB7b825E34D2b936213e0B", + "name": "Tokemak", + "symbol": "TOKE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17495/thumb/tokemak-avatar-200px-black.png?1628131614", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x502865ECDd2a2929Aa9418297bE7d3C4a7BD5Ac6", + "name": "TE FOOD", + "symbol": "TONE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2325/thumb/tec.png?1547036538", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x1ac70C9e29bC19640E64D938DD8D6A46dbAe6f2e", + "name": "OriginTrail", + "symbol": "TRAC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1877/thumb/TRAC.jpg?1635134367", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x8e902FDeA73e5CF9621D2Bee82cD79196d8ec63b", + "name": "Tellor", + "symbol": "TRB", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9644/thumb/Blk_icon_current.png?1584980686", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x437dD6360Bd17FB353c67376371133Cd33dacdBD", + "name": "Tribe", + "symbol": "TRIBE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14575/thumb/tribe.PNG?1617487954", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x55C65102C26b173696e935B1325e5AaeF30cFE0e", + "name": "TrueFi", + "symbol": "TRU", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/13180/thumb/truefi_glyph_color.png?1617610941", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x1E4339318EcE1d6D9d2Fb129b31C06b9F2d202A1", + "name": "Turbo", + "symbol": "TURBO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/30117/large/TurboMark-QL_200.png?1708079597", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x756fb781389DCaF9D3BC5468927F06A913bD9D5D", + "name": "The Virtua Kolect", + "symbol": "TVK", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13330/thumb/virtua_original.png?1656043619", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x478923278640a10A60951E379aFFb60772435f8C", + "name": "UMA Voting Token v1", + "symbol": "UMA", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xe9225a870b54f8FBA42c8188D211271f0408a30B", + "name": "Unifi Protocol DAO", + "symbol": "UNFI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13152/thumb/logo-2.png?1605748967", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x8f187aA05619a017077f5308904739877ce9eA21", + "name": "Uniswap", + "symbol": "UNI", + "decimals": 18, + "logoUrl": "ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg", + "priceUsd": "5.75" + }, + { + "chainId": 130, + "address": "0x5EAFF8Fa6f3831Bb86FeEB701E6f98293E264D36", + "name": "Pawtocol", + "symbol": "UPI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12186/thumb/pawtocol.jpg?1597962008", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x078D782b760474a361dDA0AF3839290b0EF57AD6", + "name": "USDCoin", + "symbol": "USDC", + "decimals": 6, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png", + "priceUsd": "0.999803" + }, + { + "chainId": 130, + "address": "0x2A22868610610199D43fE93A16661473A9f86f1E", + "name": "Global Dollar", + "symbol": "USDG", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/51281/large/GDN_USDG_Token_200x200.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xF7E6430137eF8087E0D472343f358e986De0FEFF", + "name": "Pax Dollar", + "symbol": "USDP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/6013/standard/Pax_Dollar.png?1696506427", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xf37748D2Cc6E6d5D05945Ce130C03c147b2F3a5F", + "name": "Quantoz USDQ", + "symbol": "USDQ", + "decimals": 6, + "logoUrl": "https://coin-images.coingecko.com/coins/images/51852/large/USDQ_1000px_Color.png?1732071232", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xaC025d055a6B633992dE1F796b97B97F004c06a7", + "name": "StablR USD", + "symbol": "USDR", + "decimals": 6, + "logoUrl": "https://coin-images.coingecko.com/coins/images/53721/large/stablrusd-logo.png?1737126629", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x116EE4d63847fb295dD919aE57B768EA3B2f7Bb4", + "name": "USDS Stablecoin", + "symbol": "USDS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/39926/large/usds.webp?1726666683", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x588CE4F028D8e7B53B687865d6A67b3A54C75518", + "name": "Tether USD", + "symbol": "USDT", + "decimals": 6, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xc7bA59c95ba747a7c374DC7208a0513798BC5950", + "name": "USUAL", + "symbol": "USUAL", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/51091/large/USUAL.jpg?1730035787", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x286b5Ecea3749c7c7047104aa3C5749901564A0b", + "name": "VANRY", + "symbol": "VANRY", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/33466/large/apple-touch-icon.png?1701942541", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x4afd08AC2416450d9c8b84D287dbfFb68FFe537f", + "name": "Voyager Token", + "symbol": "VGX", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/794/thumb/Voyager-vgx.png?1575693595", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xb86a08ec917EeF9f835aC2B26c3a506c06364A49", + "name": "Wrapped Ampleforth", + "symbol": "WAMPL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/20825/thumb/photo_2021-11-25_02-05-11.jpg?1637811951", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x927B51f251480a681271180DA4de28D44EC4AfB8", + "name": "Wrapped BTC", + "symbol": "WBTC", + "decimals": 8, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xaE87B8eb5E313AC72B306CbA7c1E3f23D72e82C4", + "name": "Wrapped Centrifuge", + "symbol": "WCFG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17106/thumb/WCFG.jpg?1626266462", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x4200000000000000000000000000000000000006", + "name": "Wrapped Ether", + "symbol": "WETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3848.45" + }, + { + "chainId": 130, + "address": "0x97Fadb3D000b953360FD011e173F12cDDB5d70Fa", + "name": "dogwifhat", + "symbol": "WIF", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/33566/standard/dogwifhat.jpg?1702499428", + "priceUsd": "0.505567" + }, + { + "chainId": 130, + "address": "0xef22b9df2dDf4246A827575C4Aa46BDaeFd89E62", + "name": "WOO Network", + "symbol": "WOO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12921/thumb/w2UiemF__400x400.jpg?1603670367", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x15261eEb999eD3C3ae3c5319E0035940dc06a12f", + "name": "Chain", + "symbol": "XCN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24210/thumb/Chain_icon_200x200.png?1646895054", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x139451953Ef1865c096F89C5e522C081DC3b5f11", + "name": "Plasma", + "symbol": "XPL", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/plasma/info/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x2615a94df961278DcbC41Fb0a54fEc5f10a693aE", + "name": "XRP", + "symbol": "XRP", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ripple/info/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xb1A9385B500Fe81B58c4d0e3AaCC39d8021265c3", + "name": "XSGD", + "symbol": "XSGD", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/12832/standard/StraitsX_Singapore_Dollar_%28XSGD%29_Token_Logo.png?1696512623", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x43D5EA0f30Bce3907aAD6783e61D56592AEbE4eA", + "name": "XYO Network", + "symbol": "XYO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4519/thumb/XYO_Network-logo.png?1547039819", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x52Bf54Eb4210F588320f3e4c151Bca81f84a3201", + "name": "yearn finance", + "symbol": "YFI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x62ffD4229bb9a327412D1BE518A1dbAe6c18A07E", + "name": "DFI money", + "symbol": "YFII", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11902/thumb/YFII-logo.78631676.png?1598677348", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0xeA20C2Cf22acBbF3d8311D15bC73FD7076E36f4B", + "name": "Yield Guild Games", + "symbol": "YGG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17358/thumb/le1nzlO6_400x400.jpg?1632465691", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x83f31af747189c2FA9E5DeB253200c505eff6ed2", + "name": "Zcash", + "symbol": "ZEC", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/zcash/info/logo.png", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x757dCF360f2FE999FAEEBcc6E80f5Eceb3cb3CA4", + "name": "Zetachain", + "symbol": "Zeta", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/26718/standard/Twitter_icon.png?1696525788", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x00ad3704d1e101DF76f87738bEfE67737eD29cFb", + "name": "LayerZero", + "symbol": "ZRO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208", + "priceUsd": null + }, + { + "chainId": 130, + "address": "0x7e7e8e5f0eDd7ca2ed3D9609cea1FF37a6E7Edf5", + "name": "0x Protocol Token", + "symbol": "ZRX", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x9c2C5fd7b07E95EE044DDeba0E97a665F142394f", + "name": "1inch", + "symbol": "1INCH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028", + "priceUsd": "0.162785429142584" + }, + { + "chainId": 137, + "address": "0xD6DF932A45C0f255f85145f286eA0b292B21C90B", + "name": "Aave", + "symbol": "AAVE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110", + "priceUsd": "218.02" + }, + { + "chainId": 137, + "address": "0xF328b73B6c685831F238c30a23Fc19140CB4D8FC", + "name": "Across Protocol Token", + "symbol": "ACX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/28161/large/across-200x200.png?1696527165", + "priceUsd": "0.065349" + }, + { + "chainId": 137, + "address": "0xdDa7b23D2D72746663E7939743f929a3d85FC975", + "name": "Ambire AdEx", + "symbol": "ADX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/847/thumb/Ambire_AdEx_Symbol_color.png?1655432540", + "priceUsd": "0.1278" + }, + { + "chainId": 137, + "address": "0xE0B52e49357Fd4DAf2c15e02058DCE6BC0057db4", + "name": "agEur", + "symbol": "agEUR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19479/standard/agEUR.png?1696518915", + "priceUsd": "1.15" + }, + { + "chainId": 137, + "address": "0x6a6bD53d677F8632631662C48bD47b1D4D6524ee", + "name": "Adventure Gold", + "symbol": "AGLD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/18125/thumb/lpgblc4h_400x400.jpg?1630570955", + "priceUsd": "0.06374543017179965" + }, + { + "chainId": 137, + "address": "0xe2341718c6C0CbFa8e6686102DD8FbF4047a9e9B", + "name": "AIOZ Network", + "symbol": "AIOZ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14631/thumb/aioz_logo.png?1617413126", + "priceUsd": "0.032278673718843916" + }, + { + "chainId": 137, + "address": "0x95c300e7740D2A88a44124B424bFC1cB2F9c3b89", + "name": "Alchemix", + "symbol": "ALCX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14113/thumb/Alchemix.png?1614409874", + "priceUsd": "8.167676736854972" + }, + { + "chainId": 137, + "address": "0x82dCf1Df86AdA26b2dCd9ba6334CeDb8c2448e9e", + "name": "Aleph im", + "symbol": "ALEPH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11676/thumb/Monochram-aleph.png?1608483725", + "priceUsd": "0.07524046874487966" + }, + { + "chainId": 137, + "address": "0xbFc70507384047Aa74c29Cdc8c5Cb88D0f7213AC", + "name": "Alethea Artificial Liquid Intelligence", + "symbol": "ALI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/22062/thumb/alethea-logo-transparent-colored.png?1642748848", + "priceUsd": "0.00376594" + }, + { + "chainId": 137, + "address": "0x50858d870FAF55da2fD90FB6DF7c34b5648305C6", + "name": "My Neighbor Alice", + "symbol": "ALICE", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/14375/thumb/alice_logo.jpg?1615782968", + "priceUsd": "0.17092854103930413" + }, + { + "chainId": 137, + "address": "0x3AE490db48d74B1bC626400135d4616377D0109f", + "name": "Alpha Venture DAO", + "symbol": "ALPHA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12738/thumb/AlphaToken_256x256.png?1617160876", + "priceUsd": "0.01075683328997803" + }, + { + "chainId": 137, + "address": "0x0621d647cecbFb64b79E44302c1933cB4f27054d", + "name": "Amp", + "symbol": "AMP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12409/thumb/amp-200x200.png?1599625397", + "priceUsd": "0.005395386216" + }, + { + "chainId": 137, + "address": "0x101A023270368c0D50BFfb62780F4aFd4ea79C35", + "name": "Ankr", + "symbol": "ANKR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4324/thumb/U85xTl2.png?1608111978", + "priceUsd": "0.010098562414107302" + }, + { + "chainId": 137, + "address": "0x2b8504ab5eFc246d0eC5Ec7E74565683227497de", + "name": "Aragon", + "symbol": "ANT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/681/thumb/JelZ58cv_400x400.png?1601449653", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xB7b31a6BC18e48888545CE79e83E06003bE70930", + "name": "ApeCoin", + "symbol": "APE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24383/small/apecoin.jpg?1647476455", + "priceUsd": "0.40085732852095124" + }, + { + "chainId": 137, + "address": "0x45C27821E80F8789b60Fd8B600C73815d34DDa6C", + "name": "API3", + "symbol": "API3", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13256/thumb/api3.jpg?1606751424", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xEE800B277A96B0f490a1A732e1D6395FAD960A26", + "name": "ARPA Chain", + "symbol": "ARPA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/8506/thumb/9u0a23XY_400x400.jpg?1559027357", + "priceUsd": "0.018401890191711873" + }, + { + "chainId": 137, + "address": "0x04bEa9FCE76943E90520489cCAb84E84C0198E29", + "name": "AirSwap", + "symbol": "AST", + "decimals": 4, + "logoUrl": "https://assets.coingecko.com/coins/images/1019/thumb/Airswap.png?1630903484", + "priceUsd": "0.37664594954404235" + }, + { + "chainId": 137, + "address": "0x0df0f72EE0e5c9B7ca761ECec42754992B2Da5BF", + "name": "Automata", + "symbol": "ATA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15985/thumb/ATA.jpg?1622535745", + "priceUsd": "0.030482886338510342" + }, + { + "chainId": 137, + "address": "0x5eB8D998371971D01954205c7AFE90A7AF6a95AC", + "name": "Audius", + "symbol": "AUDIO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12913/thumb/AudiusCoinLogo_2x.png?1603425727", + "priceUsd": "0.05283146125855833" + }, + { + "chainId": 137, + "address": "0x61BDD9C7d4dF4Bf47A4508c0c8245505F2Af5b7b", + "name": "Axie Infinity", + "symbol": "AXS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13029/thumb/axie_infinity_logo.png?1604471082", + "priceUsd": "1.4649667355123874" + }, + { + "chainId": 137, + "address": "0x1FcbE5937B0cc2adf69772D228fA4205aCF4D9b2", + "name": "Badger DAO", + "symbol": "BADGER", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13287/thumb/badger_dao_logo.jpg?1607054976", + "priceUsd": "0.5332537451537194" + }, + { + "chainId": 137, + "address": "0x9a71012B13CA4d3D0Cdc72A177DF3ef03b0E76A3", + "name": "Balancer", + "symbol": "BAL", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xba100000625a3754423978a60c9317c58a424e3D/logo.png", + "priceUsd": "0.98021" + }, + { + "chainId": 137, + "address": "0xA8b1E0764f85f53dfe21760e8AfE5446D82606ac", + "name": "Band Protocol", + "symbol": "BAND", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9545/thumb/band-protocol.png?1568730326", + "priceUsd": "0.402866525821495" + }, + { + "chainId": 137, + "address": "0x3Cef98bb43d732E2F285eE605a8158cDE967D219", + "name": "Basic Attention Token", + "symbol": "BAT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/677/thumb/basic-attention-token.png?1547034427", + "priceUsd": "0.1494095944832519" + }, + { + "chainId": 137, + "address": "0x91c89A94567980f0e9723b487b0beD586eE96aa7", + "name": "Biconomy", + "symbol": "BICO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/21061/thumb/biconomy_logo.jpg?1638269749", + "priceUsd": "0.0518373804753807" + }, + { + "chainId": 137, + "address": "0x63400d9586873eB03c84F76755D26Ef2a9a2abeF", + "name": "Big Time", + "symbol": "BIGTIME", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/32251/standard/-6136155493475923781_121.jpg?1696998691", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x438B28C5AA5F00a817b7Def7cE2Fb3d5d1970974", + "name": "Bluzelle", + "symbol": "BLZ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2848/thumb/ColorIcon_3x.png?1622516510", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xc26D47d5c33aC71AC5CF9F776D63Ba292a4F7842", + "name": "Bancor Network Token", + "symbol": "BNT", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C/logo.png", + "priceUsd": "0.4867579245680793" + }, + { + "chainId": 137, + "address": "0xa4B2B20b2C73c7046ED19AC6bfF5E5285c58F20a", + "name": "Boba Network", + "symbol": "BOBA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/20285/thumb/BOBA.png?1636811576", + "priceUsd": "0.018491787745685297" + }, + { + "chainId": 137, + "address": "0xA041544fe2BE56CCe31Ebb69102B965E06aacE80", + "name": "BarnBridge", + "symbol": "BOND", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12811/thumb/barnbridge.jpg?1602728853", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xdAb529f40E671A1D4bF91361c21bf9f0C9712ab7", + "name": "Binance USD", + "symbol": "BUSD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766", + "priceUsd": "1.0077313945130604" + }, + { + "chainId": 137, + "address": "0x91a4635F620766145C099E15889Bd2766906A559", + "name": "Celer Network", + "symbol": "CELR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4379/thumb/Celr.png?1554705437", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x594C984E3318e91313f881B021A0C4203fF5E59F", + "name": "Chromia", + "symbol": "CHR", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/5000/thumb/Chromia.png?1559038018", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xf1938Ce12400f9a761084E7A80d37e732a4dA056", + "name": "Chiliz", + "symbol": "CHZ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/8834/thumb/Chiliz.png?1561970540", + "priceUsd": "0.028573427960851622" + }, + { + "chainId": 137, + "address": "0x8505b9d2254A7Ae468c0E9dd10Ccea3A837aef5c", + "name": "Compound", + "symbol": "COMP", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png", + "priceUsd": "34.169985101036396" + }, + { + "chainId": 137, + "address": "0x5dCc7FEEEfeF110419549A4417313876D33D354c", + "name": "Clearpool", + "symbol": "CPOOL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19252/large/photo_2022-08-31_12.45.02.jpeg?1696518697", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x93B0fF1C8828F6eB039D345Ff681eD735086d925", + "name": "Covalent", + "symbol": "CQT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14168/thumb/covalent-cqt.png?1624545218", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xAdA58DF0F643D959C2A47c9D4d4c1a4deFe3F11C", + "name": "Cronos", + "symbol": "CRO", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/7310/thumb/oCw2s3GI_400x400.jpeg?1645172042", + "priceUsd": "0.1628205081943792" + }, + { + "chainId": 137, + "address": "0x172370d5Cd63279eFa6d502DAB29171933a610AF", + "name": "Curve DAO Token", + "symbol": "CRV", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xD533a949740bb3306d119CC777fa900bA034cd52/logo.png", + "priceUsd": "0.488167" + }, + { + "chainId": 137, + "address": "0x2727Ab1c2D22170ABc9b595177B2D5C6E1Ab7B7B", + "name": "Cartesi", + "symbol": "CTSI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021", + "priceUsd": "0.08081889340644874" + }, + { + "chainId": 137, + "address": "0x8c208BC2A808a088a78398fed8f2640cab0b6EDb", + "name": "Cryptex Finance", + "symbol": "CTX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14932/thumb/glossy_icon_-_C200px.png?1619073171", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x276C9cbaa4BDf57d7109a41e67BD09699536FA3d", + "name": "Somnium Space CUBEs", + "symbol": "CUBE", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/10687/thumb/CUBE_icon.png?1617026861", + "priceUsd": "0.26568833827820776" + }, + { + "chainId": 137, + "address": "0x66Dc5A08091d1968e08C16aA5b27BAC8398b02Be", + "name": "Civic", + "symbol": "CVC", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/788/thumb/civic.png?1547034556", + "priceUsd": "0.056684" + }, + { + "chainId": 137, + "address": "0x4257EA7637c355F81616050CbB6a9b709fd72683", + "name": "Convex Finance", + "symbol": "CVX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15585/thumb/convex.png?1621256328", + "priceUsd": "2.1327054988237433" + }, + { + "chainId": 137, + "address": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", + "name": "Dai Stablecoin", + "symbol": "DAI", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png", + "priceUsd": "0.999821" + }, + { + "chainId": 137, + "address": "0x26f5FB1e6C8a65b3A873fF0a213FA16EFF5a7828", + "name": "DerivaDAO", + "symbol": "DDX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13453/thumb/ddx_logo.png?1608741641", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xff835562C761205659939B64583dd381a6AA4D92", + "name": "DexTools", + "symbol": "DEXT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11603/thumb/dext.png?1605790188", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x993f2CafE9dbE525243f4A78BeBC69DAc8D36000", + "name": "DIA", + "symbol": "DIA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11955/thumb/image.png?1646041751", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x85955046DF4668e1DD369D2DE9f3AEB98DD2A369", + "name": "DeFi Pulse Index", + "symbol": "DPI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12465/thumb/defi_pulse_index_set.png?1600051053", + "priceUsd": "77.60467656412433" + }, + { + "chainId": 137, + "address": "0x4C3bF0a3DE9524aF68327d1D2558a3B70d17D42a", + "name": "dYdX", + "symbol": "DYDX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17500/thumb/hjnIm9bV.jpg?1628009360", + "priceUsd": "0.04373314696" + }, + { + "chainId": 137, + "address": "0xE0339c80fFDE91F3e20494Df88d4206D86024cdF", + "name": "Dogelon Mars", + "symbol": "ELON", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14962/thumb/6GxcPRo3_400x400.jpg?1619157413", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x7eC26842F195c852Fa843bB9f6D8B583a274a157", + "name": "Enjin Coin", + "symbol": "ENJ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1102/thumb/enjin-coin-logo.png?1547035078", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xbD7A5Cf51d22930B8B3Df6d834F9BCEf90EE7c4f", + "name": "Ethereum Name Service", + "symbol": "ENS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19785/thumb/acatxTm8_400x400.jpg?1635850140", + "priceUsd": "14.847427261200341" + }, + { + "chainId": 137, + "address": "0x0E50BEA95Fe001A370A4F1C220C49AEdCB982DeC", + "name": "Ethernity Chain", + "symbol": "ERN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14238/thumb/LOGO_HIGH_QUALITY.png?1647831402", + "priceUsd": "0.06719459891660214" + }, + { + "chainId": 137, + "address": "0x8a037dbcA8134FFc72C362e394e35E0Cad618F85", + "name": "Euro Coin", + "symbol": "EURC", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/26045/thumb/euro-coin.png?1655394420", + "priceUsd": "1.922837328912463" + }, + { + "chainId": 137, + "address": "0x176f5AB638cf4Ff3B6239Ba609C3fadAA46ef5B0", + "name": "Harvest Finance", + "symbol": "FARM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12304/thumb/Harvest.png?1613016180", + "priceUsd": "189794803243.78656" + }, + { + "chainId": 137, + "address": "0x7583FEDDbceFA813dc18259940F76a02710A8905", + "name": "Fetch ai", + "symbol": "FET", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/5681/thumb/Fetch.jpg?1572098136", + "priceUsd": "0.21755161722128033" + }, + { + "chainId": 137, + "address": "0x7A7B94F18EF6AD056CDa648588181CDA84800f94", + "name": "Stafi", + "symbol": "FIS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12423/thumb/stafi_logo.jpg?1599730991", + "priceUsd": "0.1394385950595252" + }, + { + "chainId": 137, + "address": "0x853B41823905aB4d63558542b0F06748A5e345fe", + "name": "FLOKI", + "symbol": "FLOKI", + "decimals": 9, + "logoUrl": "https://assets.coingecko.com/coins/images/16746/standard/PNG_image.png?1696516318", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x9ff62d1FC52A907B6DCbA8077c2DDCA6E6a9d3e1", + "name": "Forta", + "symbol": "FORT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/25060/thumb/Forta_lgo_%281%29.png?1655353696", + "priceUsd": "0.05431826550543558" + }, + { + "chainId": 137, + "address": "0x5eCbA59DAcc1ADc5bDEA35f38A732823fc3dE977", + "name": "Ampleforth Governance Token", + "symbol": "FORTH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14917/thumb/photo_2021-04-22_00.00.03.jpeg?1619020835", + "priceUsd": "19.262505650581918" + }, + { + "chainId": 137, + "address": "0x65A05DB8322701724c197AF82C9CaE41195B0aA8", + "name": "ShapeShift FOX Token", + "symbol": "FOX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9988/thumb/FOX.png?1574330622", + "priceUsd": "0.01933155" + }, + { + "chainId": 137, + "address": "0x104592a158490a9228070E0A8e5343B499e125D0", + "name": "Frax", + "symbol": "FRAX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13422/thumb/frax_logo.png?1608476506", + "priceUsd": "1.0061593136191094" + }, + { + "chainId": 137, + "address": "0xC9c1c1c20B3658F8787CC2FD702267791f224Ce1", + "name": "Fantom", + "symbol": "FTM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4001/thumb/Fantom.png?1558015016", + "priceUsd": "0.148688197" + }, + { + "chainId": 137, + "address": "0x3e121107F6F22DA4911079845a470757aF4e1A1b", + "name": "Frax Share", + "symbol": "FXS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13423/thumb/frax_share.png?1608478989", + "priceUsd": "1.33945383412504" + }, + { + "chainId": 137, + "address": "0x385Eeac5cB85A38A9a07A70c73e0a3271CfB54A7", + "name": "Aavegotchi", + "symbol": "GHST", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12467/thumb/ghst_200.png?1600750321", + "priceUsd": "0.294162" + }, + { + "chainId": 137, + "address": "0x0B220b82F3eA3B7F6d9A1D8ab58930C064A2b5Bf", + "name": "Golem", + "symbol": "GLM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/542/thumb/Golem_Submark_Positive_RGB.png?1606392013", + "priceUsd": "0.18524615717840429" + }, + { + "chainId": 137, + "address": "0x5FFD62D3C3eE2E81C00A7b9079FB248e7dF024A8", + "name": "Gnosis Token", + "symbol": "GNO", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6810e776880C02933D47DB1b9fc05908e5386b96/logo.png", + "priceUsd": "29.521654768610144" + }, + { + "chainId": 137, + "address": "0xF88fc6b493eda7650E4bcf7A290E8d108F677CfE", + "name": "Gods Unchained", + "symbol": "GODS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17139/thumb/10631.png?1635718182", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x5fe2B58c013d7601147DcdD68C143A77499f5531", + "name": "The Graph", + "symbol": "GRT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13397/thumb/Graph_Token.png?1608145566", + "priceUsd": "0.062084" + }, + { + "chainId": 137, + "address": "0xdb95f9188479575F3F718a245EcA1B3BF74567EC", + "name": "Gitcoin", + "symbol": "GTC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15810/thumb/gitcoin.png?1621992929", + "priceUsd": "0.252683087324173" + }, + { + "chainId": 137, + "address": "0xC8A94a3d3D2dabC3C1CaffFFDcA6A7543c3e3e65", + "name": "Gemini Dollar", + "symbol": "GUSD", + "decimals": 2, + "logoUrl": "https://assets.coingecko.com/coins/images/5992/thumb/gemini-dollar-gusd.png?1536745278", + "priceUsd": "0.7636519709780811" + }, + { + "chainId": 137, + "address": "0x482bc619eE7662759CDc0685B4E78f464Da39C73", + "name": "GYEN", + "symbol": "GYEN", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/14191/thumb/icon_gyen_200_200.png?1614843343", + "priceUsd": "0.0017804636678318212" + }, + { + "chainId": 137, + "address": "0x6cCBF3627b2C83AFEF05bf2F035E7f7B210Fe30D", + "name": "HOPR", + "symbol": "HOPR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14061/thumb/Shared_HOPR_logo_512px.png?1614073468", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x9Cb74C8032b007466865f060ad2c46145d45553D", + "name": "IDEX", + "symbol": "IDEX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2565/thumb/logomark-purple-286x286.png?1638362736", + "priceUsd": "0.019563146284242976" + }, + { + "chainId": 137, + "address": "0xFA46dAf9909e116DBc40Fe1cC95fC0Bb1f452aBE", + "name": "Illuvium", + "symbol": "ILV", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14468/large/ILV.JPG", + "priceUsd": "16.35049329964252" + }, + { + "chainId": 137, + "address": "0x183070C90B34A63292cC908Ce1b263Cb56D49A7F", + "name": "Immutable X", + "symbol": "IMX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17233/thumb/imx.png?1636691817", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xfBd8A3b908e764dBcD51e27992464B4432A1132b", + "name": "Index Cooperative", + "symbol": "INDEX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12729/thumb/index.png?1634894321", + "priceUsd": "0.988717" + }, + { + "chainId": 137, + "address": "0x4E8dc2149EaC3f3dEf36b1c281EA466338249371", + "name": "Injective", + "symbol": "INJ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12882/thumb/Secondary_Symbol.png?1628233237", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xF18Ac368001b0DdC80aA6a8374deb49e868EFDb8", + "name": "Inverse Finance", + "symbol": "INV", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14205/thumb/inverse_finance.jpg?1614921871", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xf6372cDb9c1d3674E83842e3800F2A62aC9F3C66", + "name": "IoTeX", + "symbol": "IOTX", + "decimals": 18, + "logoUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/2777.png", + "priceUsd": "0.008233919549725426" + }, + { + "chainId": 137, + "address": "0xb87f5c1E81077FfcfE821dA240fd20C99c533aF1", + "name": "JasmyCoin", + "symbol": "JASMY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13876/thumb/JASMY200x200.jpg?1612473259", + "priceUsd": "0.010396965398029874" + }, + { + "chainId": 137, + "address": "0x42f37A1296b2981F7C3cAcEd84c5096b2Eb0C72C", + "name": "Keep Network", + "symbol": "KEEP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3373/thumb/IuNzUb5b_400x400.jpg?1589526336", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x324b28d6565f784d596422B0F2E5aB6e9CFA1Dc7", + "name": "Kyber Network Crystal", + "symbol": "KNC", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdd974D5C2e2928deA5F71b9825b8b646686BD200/logo.png", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x53AEc293212E3B792563Bc16f1be26956adb12e9", + "name": "Keep3rV1", + "symbol": "KP3R", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12966/thumb/kp3r_logo.jpg?1607057458", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xE8A51D0dD1b4525189ddA2187F90ddF0932b5482", + "name": "LCX", + "symbol": "LCX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9985/thumb/zRPSu_0o_400x400.jpg?1574327008", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xC3C7d422809852031b44ab29EEC9F1EfF2A58756", + "name": "Lido DAO", + "symbol": "LDO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13573/thumb/Lido_DAO.png?1609873644", + "priceUsd": "0.864329" + }, + { + "chainId": 137, + "address": "0x53E0bca35eC356BD5ddDFebbD1Fc0fD03FaBad39", + "name": "ChainLink Token", + "symbol": "LINK", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png", + "priceUsd": "17.15" + }, + { + "chainId": 137, + "address": "0xe6E320b7bB22018D6CA1F4D8cea1365eF5d25ced", + "name": "Litentry", + "symbol": "LIT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13825/large/logo_200x200.png", + "priceUsd": "4.493114861157932" + }, + { + "chainId": 137, + "address": "0x465b67CB20A7E8bC4c51b4C7DA591C1945b41427", + "name": "League of Kingdoms", + "symbol": "LOKA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/22572/thumb/loka_64pix.png?1642643271", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x66EfB7cC647e0efab02eBA4316a2d2941193F6b3", + "name": "Loom Network", + "symbol": "LOOM", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0/logo.png", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x3962F4A0A0051DccE0be73A7e09cEf5756736712", + "name": "Livepeer", + "symbol": "LPT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/7137/thumb/logo-circle-green.png?1619593365", + "priceUsd": "0.0017176720359301082" + }, + { + "chainId": 137, + "address": "0x8Ab2Fec94d17ae69FB90E7c773f2C85Ed1802c01", + "name": "Liquity", + "symbol": "LQTY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14665/thumb/200-lqty-icon.png?1617631180", + "priceUsd": "0.014500307663417459" + }, + { + "chainId": 137, + "address": "0x84e1670F61347CDaeD56dcc736FB990fBB47ddC1", + "name": "LoopringCoin V2", + "symbol": "LRC", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD/logo.png", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x23001f892c0C82b79303EDC9B9033cD190BB21c7", + "name": "Liquity USD", + "symbol": "LUSD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14666/thumb/Group_3.png?1617631327", + "priceUsd": "1.0206911525873907" + }, + { + "chainId": 137, + "address": "0xA1c57f48F0Deb89f569dFbE6E2B7f46D33606fD4", + "name": "Decentraland", + "symbol": "MANA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/878/thumb/decentraland-mana.png?1550108745", + "priceUsd": "0.2292507110049314" + }, + { + "chainId": 137, + "address": "0x2B9E7ccDF0F4e5B24757c1E1a80e311E34Cb10c7", + "name": "Mask Network", + "symbol": "MASK", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14051/thumb/Mask_Network.jpg?1614050316", + "priceUsd": "0.813972" + }, + { + "chainId": 137, + "address": "0x347ACCAFdA7F8c5BdeC57fa34a5b663CBd1aeca7", + "name": "MATH", + "symbol": "MATH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11335/thumb/2020-05-19-token-200.png?1589940590", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x0000000000000000000000000000000000001010", + "name": "Polygon", + "symbol": "MATIC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xAa7DbD1598251f856C12f63557A4C4397c253Cea", + "name": "Moss Carbon Credit", + "symbol": "MCO2", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14414/thumb/ENtxnThA_400x400.jpg?1615948522", + "priceUsd": "0.18585932048523468" + }, + { + "chainId": 137, + "address": "0x1B9D40715E757Bdb9bdEC3215B898E46d8a3b71a", + "name": "Metis", + "symbol": "METIS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15595/thumb/metis.jpeg?1660285312", + "priceUsd": "263416.8433930186" + }, + { + "chainId": 137, + "address": "0x01288e04435bFcd4718FF203D6eD18146C17Cd4b", + "name": "Magic Internet Money", + "symbol": "MIM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/16786/thumb/mimlogopng.png?1624979612", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x1C5cccA2CB59145A4B25F452660cbA6436DDce9b", + "name": "Mirror Protocol", + "symbol": "MIR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13295/thumb/mirror_logo_transparent.png?1611554658", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x6f7C932e7684666C9fd1d44527765433e01fF61d", + "name": "Maker", + "symbol": "MKR", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2/logo.png", + "priceUsd": "1382.4198392489486" + }, + { + "chainId": 137, + "address": "0xa9f37D84c856fDa3812ad0519Dad44FA0a3Fe207", + "name": "Melon", + "symbol": "MLN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/605/thumb/melon.png?1547034295", + "priceUsd": "6.62" + }, + { + "chainId": 137, + "address": "0x6968105460f67c3BF751bE7C15f92F5286Fd0CE5", + "name": "Monavale", + "symbol": "MONA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13298/thumb/monavale_logo.jpg?1607232721", + "priceUsd": "62.82198691598507" + }, + { + "chainId": 137, + "address": "0xA3c322Ad15218fBFAEd26bA7f616249f7705D945", + "name": "GensoKishi Metaverse", + "symbol": "MV", + "decimals": 18, + "logoUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/17704.png", + "priceUsd": "0.005680105242654531" + }, + { + "chainId": 137, + "address": "0x4985E0B13554fB521840e893574D3848C10Fcc6f", + "name": "PolySwarm", + "symbol": "NCT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2843/thumb/ImcYCVfX_400x400.jpg?1628519767", + "priceUsd": "0.01566929" + }, + { + "chainId": 137, + "address": "0x0Bf519071b02F22C17E7Ed5F4002ee1911f46729", + "name": "Numeraire", + "symbol": "NMR", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671/logo.png", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x282d8efCe846A88B159800bd4130ad77443Fa1A1", + "name": "Ocean Protocol", + "symbol": "OCEAN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3687/thumb/ocean-protocol-logo.jpg?1547038686", + "priceUsd": "0.2978297766092384" + }, + { + "chainId": 137, + "address": "0xa63Beffd33AB3a2EfD92a39A7D2361CEE14cEbA8", + "name": "Origin Protocol", + "symbol": "OGN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3296/thumb/op.jpg?1547037878", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x62414D03084EeB269E18C970a21f45D2967F0170", + "name": "OMG Network", + "symbol": "OMG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/776/thumb/OMG_Network.jpg?1591167168", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x0EE392bA5ef1354c9bd75a98044667d307C0e773", + "name": "Orion Protocol", + "symbol": "ORN", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/11841/thumb/orion_logo.png?1594943318", + "priceUsd": "0.1223170672479405" + }, + { + "chainId": 137, + "address": "0x9880e3dDA13c8e7D4804691A45160102d31F6060", + "name": "Orchid", + "symbol": "OXT", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x4575f41308EC1483f3d399aa9a2826d74Da13Deb/logo.png", + "priceUsd": "0.023518136061931857" + }, + { + "chainId": 137, + "address": "0x553d3D295e0f695B9228246232eDF400ed3560B5", + "name": "PAX Gold", + "symbol": "PAXG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9519/thumb/paxg.PNG?1568542565", + "priceUsd": "3996.6156850319503" + }, + { + "chainId": 137, + "address": "0x1D47e931F82bb9F8D967F0Cc3288268449835806", + "name": "Pendle", + "symbol": "PENDLE", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/15069/large/Pendle_Logo_Normal-03.png?1696514728", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x263534a4Fe3cb249dF46810718B7B612a30ebbff", + "name": "Perpetual Protocol", + "symbol": "PERP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x7dc0cb65EC6019330a6841e9c274f2EE57A6CA6C", + "name": "Pluton", + "symbol": "PLU", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1241/thumb/pluton.png?1548331624", + "priceUsd": "54.54657650382103" + }, + { + "chainId": 137, + "address": "0x8dc302e2141DA59c934d900886DbF1518Fd92cd4", + "name": "Polkastarter", + "symbol": "POLS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12648/thumb/polkastarter.png?1609813702", + "priceUsd": "107.62616396124756" + }, + { + "chainId": 137, + "address": "0xcB059C5573646047D6d88dDdb87B745C18161d3b", + "name": "Polymath", + "symbol": "POLY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2784/thumb/inKkF01.png?1605007034", + "priceUsd": "0.10337844719466627" + }, + { + "chainId": 137, + "address": "0x73580A2416A57f1C4b6391DBA688A9e4f7DBECE0", + "name": "Marlin", + "symbol": "POND", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/8903/thumb/POND_200x200.png?1622515451", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x0AaB8DC887D34f00D50E19aee48371a941390d14", + "name": "Power Ledger", + "symbol": "POWR", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/1104/thumb/power-ledger.png?1547035082", + "priceUsd": "85.06051515644072" + }, + { + "chainId": 137, + "address": "0x82FFdFD1d8699E8886a4e77CeFA9dd9710a7FefD", + "name": "Propy", + "symbol": "PRO", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/869/thumb/propy.png?1548332100", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x9377Eeb7419486FD4D485671d50baa4BF77c2222", + "name": "PARSIQ", + "symbol": "PRQ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11973/thumb/DsNgK0O.png?1596590280", + "priceUsd": "63065245202412770" + }, + { + "chainId": 137, + "address": "0x36B77a184bE8ee56f5E81C56727B20647A42e28E", + "name": "Quant", + "symbol": "QNT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3370/thumb/5ZOu7brX_400x400.jpg?1612437252", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x831753DD7087CaC61aB5644b308642cc1c33Dc13", + "name": "Quickswap", + "symbol": "QUICK", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13970/thumb/1_pOU6pBMEmiL-ZJVb0CYRjQ.png?1613386659", + "priceUsd": "18.363471645826547" + }, + { + "chainId": 137, + "address": "0x2f81e176471CC57fDC76f7d332FB4511bF2bebDD", + "name": "Radicle", + "symbol": "RAD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14013/thumb/radicle.png?1614402918", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x00e5646f60AC6Fb446f621d146B6E1886f002905", + "name": "Rai Reflex Index", + "symbol": "RAI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14004/thumb/RAI-logo-coin.png?1613592334", + "priceUsd": "4.081397194121635" + }, + { + "chainId": 137, + "address": "0x780053837cE2CeEaD2A90D9151aA21FC89eD49c2", + "name": "Rarible", + "symbol": "RARI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11845/thumb/Rari.png?1594946953", + "priceUsd": "1.158531123169827" + }, + { + "chainId": 137, + "address": "0xc3cFFDAf8F3fdF07da6D5e3A89B8723D5E385ff8", + "name": "Rubic", + "symbol": "RBC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12629/thumb/200x200.png?1607952509", + "priceUsd": "0.008746267513476512" + }, + { + "chainId": 137, + "address": "0x19782D3Dc4701cEeeDcD90f0993f0A9126ed89d0", + "name": "Republic Token", + "symbol": "REN", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x408e41876cCCDC0F92210600ef50372656052a38/logo.png", + "priceUsd": "0.705988787418294" + }, + { + "chainId": 137, + "address": "0x6563c1244820CfBd6Ca8820FBdf0f2847363F733", + "name": "Reputation Augur v2", + "symbol": "REPv2", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x221657776846890989a759BA2973e427DfF5C9bB/logo.png", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xAdf2F2Ed91755eA3f4bcC9107a494879f633ae7C", + "name": "Request", + "symbol": "REQ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1031/thumb/Request_icon_green.png?1643250951", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x70c006878a5A50Ed185ac4C87d837633923De296", + "name": "REVV", + "symbol": "REVV", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12373/thumb/REVV_TOKEN_Refined_2021_%281%29.png?1627652390", + "priceUsd": "0.0008438318094825496" + }, + { + "chainId": 137, + "address": "0x3b9dB434F08003A89554CDB43b3e0b1f8734BdE7", + "name": "Rari Governance Token", + "symbol": "RGT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12900/thumb/Rari_Logo_Transparent.png?1613978014", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xbe662058e00849C3Eef2AC9664f37fEfdF2cdbFE", + "name": "iExec RLC", + "symbol": "RLC", + "decimals": 9, + "logoUrl": "https://assets.coingecko.com/coins/images/646/thumb/pL1VuXm.png?1604543202", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x76b8D57e5ac6afAc5D415a054453d1DD2c3C0094", + "name": "Rally", + "symbol": "RLY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12843/thumb/image.png?1611212077", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x61299774020dA444Af134c82fa83E3810b309991", + "name": "Render Token", + "symbol": "RNDR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11636/thumb/rndr.png?1638840934", + "priceUsd": "0.15954505807354932" + }, + { + "chainId": 137, + "address": "0xF92501c8213da1D6C74A76372CCc720Dc8818407", + "name": "Rook", + "symbol": "ROOK", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13005/thumb/keeper_dao_logo.jpg?1604316506", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xBbba073C31bF03b8ACf7c28EF0738DeCF3695683", + "name": "The Sandbox", + "symbol": "SAND", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12129/thumb/sandbox_logo.jpg?1597397942", + "priceUsd": "0.201496" + }, + { + "chainId": 137, + "address": "0x1d734A02eF1e1f5886e66b0673b71Af5B53ffA94", + "name": "Stader", + "symbol": "SD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/20658/standard/SD_Token_Logo.png", + "priceUsd": "0.418763" + }, + { + "chainId": 137, + "address": "0x6f8a06447Ff6FcF75d803135a7de15CE88C1d4ec", + "name": "Shiba Inu", + "symbol": "SHIB", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11939/thumb/shiba.png?1622619446", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x0C7304fBAf2A320a1c50c46FE03752722F729946", + "name": "Smooth Love Potion", + "symbol": "SLP", + "decimals": 0, + "logoUrl": "https://assets.coingecko.com/coins/images/10366/thumb/SLP.png?1578640057", + "priceUsd": "0.001138340146945385" + }, + { + "chainId": 137, + "address": "0x50B728D8D964fd00C2d0AAD81718b71311feF68a", + "name": "Synthetix Network Token", + "symbol": "SNX", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png", + "priceUsd": "0.997062" + }, + { + "chainId": 137, + "address": "0xcdB3C70CD25FD15307D84C4F9D37d5C043B33Fb2", + "name": "Spell Token", + "symbol": "SPELL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15861/thumb/abracadabra-3.png?1622544862", + "priceUsd": "0.004427070534098672" + }, + { + "chainId": 137, + "address": "0xd72357dAcA2cF11A5F155b9FF7880E595A3F5792", + "name": "Storj Token", + "symbol": "STORJ", + "decimals": 8, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC/logo.png", + "priceUsd": "0.21325618158936022" + }, + { + "chainId": 137, + "address": "0xB36e3391B22a970d31A9b620Ae1A414C6c256d2a", + "name": "Stox", + "symbol": "STX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1230/thumb/stox-token.png?1547035256", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x60Ea918FC64360269Da4efBDA11d8fC6514617C6", + "name": "SUKU", + "symbol": "SUKU", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11969/thumb/UmfW5S6f_400x400.jpg?1596602238", + "priceUsd": "0.021786811458531223" + }, + { + "chainId": 137, + "address": "0xa1428174F516F527fafdD146b883bB4428682737", + "name": "SuperFarm", + "symbol": "SUPER", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14040/thumb/6YPdWn6.png?1613975899", + "priceUsd": "0.3662870826699369" + }, + { + "chainId": 137, + "address": "0xF81b4Bec6Ca8f9fe7bE01CA734F55B2b6e03A7a0", + "name": "Synth sUSD", + "symbol": "sUSD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/5013/thumb/sUSD.png?1616150765", + "priceUsd": "0.7077203786210418" + }, + { + "chainId": 137, + "address": "0x0b3F868E0BE5597D5DB7fEB59E1CADBb0fdDa50a", + "name": "Sushi", + "symbol": "SUSHI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688", + "priceUsd": "0.493344" + }, + { + "chainId": 137, + "address": "0x6aBB753C1893194DE4a83c6e8B4EadFc105Fd5f5", + "name": "Swipe", + "symbol": "SXP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9368/thumb/swipe.png?1566792311", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xe1708AbDE4847B4929b70547E5197F1Ba1db2250", + "name": "Tokemak", + "symbol": "TOKE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17495/thumb/tokemak-avatar-200px-black.png?1628131614", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xA7b98d63a137bF402b4570799ac4caD0BB1c4B1c", + "name": "OriginTrail", + "symbol": "TRAC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1877/thumb/TRAC.jpg?1635134367", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xE3322702BEdaaEd36CdDAb233360B939775ae5f1", + "name": "Tellor", + "symbol": "TRB", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9644/thumb/Blk_icon_current.png?1584980686", + "priceUsd": "25.24" + }, + { + "chainId": 137, + "address": "0x8676815789211E799a6DC86d02748ADF9cF86836", + "name": "Tribe", + "symbol": "TRIBE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14575/thumb/tribe.PNG?1617487954", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x5b77bCA482bd3E7958b1103d123888EfCCDaF803", + "name": "TrueFi", + "symbol": "TRU", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/13180/thumb/truefi_glyph_color.png?1617610941", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x5667dcC0ab74D1b1355C3b2061893399331B57e2", + "name": "The Virtua Kolect", + "symbol": "TVK", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13330/thumb/virtua_original.png?1656043619", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x3066818837c5e6eD6601bd5a91B0762877A6B731", + "name": "UMA Voting Token v1", + "symbol": "UMA", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828/logo.png", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xb33EaAd8d922B1083446DC23f610c2567fB5180f", + "name": "Uniswap", + "symbol": "UNI", + "decimals": 18, + "logoUrl": "ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg", + "priceUsd": "5.75" + }, + { + "chainId": 137, + "address": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", + "name": "USDCoin", + "symbol": "USDC", + "decimals": 6, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png", + "priceUsd": "0.999803" + }, + { + "chainId": 137, + "address": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", + "name": "USDCoin (PoS)", + "symbol": "USDC.e", + "decimals": 6, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png", + "priceUsd": "0.999803" + }, + { + "chainId": 137, + "address": "0x6F3B3286fd86d8b47EC737CEB3D0D354cc657B3e", + "name": "Pax Dollar", + "symbol": "USDP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/6013/standard/Pax_Dollar.png?1696506427", + "priceUsd": "3523692.69337386" + }, + { + "chainId": 137, + "address": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", + "name": "Tether USD", + "symbol": "USDT", + "decimals": 6, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png", + "priceUsd": "0.99984" + }, + { + "chainId": 137, + "address": "0x8DE5B80a0C1B02Fe4976851D030B36122dbb8624", + "name": "Vanar Chain", + "symbol": "VANRY", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/33466/large/apple-touch-icon.png?1701942541", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0xd0258a3fD00f38aa8090dfee343f10A9D4d30D3F", + "name": "Voxies", + "symbol": "VOXEL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/21260/large/voxies.png", + "priceUsd": "0.03714661" + }, + { + "chainId": 137, + "address": "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6", + "name": "Wrapped BTC", + "symbol": "WBTC", + "decimals": 8, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png", + "priceUsd": "109583" + }, + { + "chainId": 137, + "address": "0x90bb6fEB70A9a43CfAaA615F856BA309FD759A90", + "name": "Wrapped Centrifuge", + "symbol": "WCFG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17106/thumb/WCFG.jpg?1626266462", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", + "name": "Wrapped Ether", + "symbol": "WETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3844.75" + }, + { + "chainId": 137, + "address": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", + "name": "Wrapped Matic", + "symbol": "WMATIC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912", + "priceUsd": "0.196342" + }, + { + "chainId": 137, + "address": "0x1B815d120B3eF02039Ee11dC2d33DE7aA4a8C603", + "name": "WOO Network", + "symbol": "WOO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12921/thumb/w2UiemF__400x400.jpg?1603670367", + "priceUsd": "0.037366115114621234" + }, + { + "chainId": 137, + "address": "0xDC3326e71D45186F113a2F448984CA0e8D201995", + "name": "XSGD", + "symbol": "XSGD", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/12832/standard/StraitsX_Singapore_Dollar_%28XSGD%29_Token_Logo.png?1696512623", + "priceUsd": "0.7690000404007074" + }, + { + "chainId": 137, + "address": "0xd2507e7b5794179380673870d88B22F94da6abe0", + "name": "XYO Network", + "symbol": "XYO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4519/thumb/XYO_Network-logo.png?1547039819", + "priceUsd": "0.007936364944" + }, + { + "chainId": 137, + "address": "0xDA537104D6A5edd53c6fBba9A898708E465260b6", + "name": "yearn finance", + "symbol": "YFI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330", + "priceUsd": "4570.57632664183" + }, + { + "chainId": 137, + "address": "0xb8cb8a7F4C2885C03e57E973C74827909Fdc2032", + "name": "DFI money", + "symbol": "YFII", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11902/thumb/YFII-logo.78631676.png?1598677348", + "priceUsd": null + }, + { + "chainId": 137, + "address": "0x82617aA52dddf5Ed9Bb7B370ED777b3182A30fd1", + "name": "Yield Guild Games", + "symbol": "YGG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17358/thumb/le1nzlO6_400x400.jpg?1632465691", + "priceUsd": "0.11901" + }, + { + "chainId": 137, + "address": "0x6985884C4392D348587B19cb9eAAf157F13271cd", + "name": "LayerZero", + "symbol": "ZRO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208", + "priceUsd": "1.55" + }, + { + "chainId": 137, + "address": "0x5559Edb74751A0edE9DeA4DC23aeE72cCA6bE3D5", + "name": "0x Protocol Token", + "symbol": "ZRX", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png", + "priceUsd": null + }, + { + "chainId": 324, + "address": "0x5A7d6b2F92C77FAD6CCaBd7EE0624E64907Eaf3E", + "name": "ZKsync", + "symbol": "ZK", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/38043/large/ZKTokenBlack.png?17186145029", + "priceUsd": "0.02938374" + }, + { + "chainId": 480, + "address": "0x79A02482A880bCE3F13e09Da970dC34db4CD24d1", + "name": "Bridged USDC", + "symbol": "USDC.e", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/35218/large/USDC_Icon.png?1707908537", + "priceUsd": "0.999803" + }, + { + "chainId": 480, + "address": "0x03C7054BCB39f7b2e5B2c7AcB37583e32D70Cfa3", + "name": "Wrapped BTC", + "symbol": "WBTC", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/7598/large/wrapped_bitcoin_wbtc.png?1696507857", + "priceUsd": "109613.72584331484" + }, + { + "chainId": 480, + "address": "0x4200000000000000000000000000000000000006", + "name": "Wrapped Ether", + "symbol": "WETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3852.4" + }, + { + "chainId": 1868, + "address": "0xbA9986D2381edf1DA03B0B9c1f8b00dc4AacC369", + "name": "USDCoin", + "symbol": "USDC", + "decimals": 6, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png", + "priceUsd": "0.999577" + }, + { + "chainId": 1868, + "address": "0x3A337a6adA9d885b6Ad95ec48F9b75f197b5AE35", + "name": "Tether USD", + "symbol": "USDT", + "decimals": 6, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png", + "priceUsd": "0.999266" + }, + { + "chainId": 1868, + "address": "0x4200000000000000000000000000000000000006", + "name": "Wrapped Ether", + "symbol": "WETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3853.26" + }, + { + "chainId": 8453, + "address": "0xc5fecC3a29Fb57B5024eEc8a2239d4621e111CBE", + "name": "1inch", + "symbol": "1INCH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0x63706e401c06ac8513145b7687A14804d17f814b", + "name": "Aave", + "symbol": "AAVE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110", + "priceUsd": "218.02" + }, + { + "chainId": 8453, + "address": "0xe2A8cCB00E328a0EC2204CB0c736309D7c1fa556", + "name": "Arcblock", + "symbol": "ABT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2341/thumb/arcblock.png?1547036543", + "priceUsd": "0.5405725828863388" + }, + { + "chainId": 8453, + "address": "0x3c87e7AF3cDBAe5bB56b4936325Ea95CA3E0EfD9", + "name": "Ambire AdEx", + "symbol": "ADX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/847/thumb/Ambire_AdEx_Symbol_color.png?1655432540", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0x940181a94A35A4569E4529A3CDfB74e38FD98631", + "name": "Aerodrome Finance", + "symbol": "AERO", + "decimals": 18, + "logoUrl": "https://basescan.org/token/images/aerodrome_32.png", + "priceUsd": "1.093" + }, + { + "chainId": 8453, + "address": "0x4F9Fd6Be4a90f2620860d680c0d4d5Fb53d1A825", + "name": "aixbt by Virtuals", + "symbol": "AIXBT", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/51784/large/3.png?1731981138", + "priceUsd": "0.077964" + }, + { + "chainId": 8453, + "address": "0x97c806e7665d3AFd84A8Fe1837921403D59F3Dcc", + "name": "Alethea Artificial Liquid Intelligence", + "symbol": "ALI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/22062/thumb/alethea-logo-transparent-colored.png?1642748848", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0x1B4617734C43F6159F3a70b7E06d883647512778", + "name": "AWE Network", + "symbol": "AWE", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/8713/large/awe-network.jpg?1747816016", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0xB3B32F9f8827D4634fE7d973Fa1034Ec9fdDB3B3", + "name": "B3", + "symbol": "B3", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/54287/large/B3.png?1739001374", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0x2a06A17CBC6d0032Cac2c6696DA90f29D39a1a29", + "name": "HarryPotterObamaSonic10Inu", + "symbol": "BITCOIN", + "decimals": 8, + "logoUrl": "https://coin-images.coingecko.com/coins/images/30323/large/hpos10i_logo_casino_night-dexview.png?1696529224", + "priceUsd": "0.061266" + }, + { + "chainId": 8453, + "address": "0x22aF33FE49fD1Fa80c7149773dDe5890D3c76F3b", + "name": "BankrCoin", + "symbol": "BNKR", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/52626/large/bankr-static.png?1736405365", + "priceUsd": "0.00055976" + }, + { + "chainId": 8453, + "address": "0x1F9bD96DDB4Bd07d6061f8933e9bA9EDE9967550", + "name": "Boba Network", + "symbol": "BOBA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/20285/thumb/BOBA.png?1636811576", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0xA7d68d155d17cB30e311367c2Ef1E82aB6022b67", + "name": "Braintrust", + "symbol": "BTRST", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/18100/thumb/braintrust.PNG?1630475394", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0xcbADA732173e39521CDBE8bf59a6Dc85A9fc7b8c", + "name": "Coinbase Wrapped ADA", + "symbol": "cbADA", + "decimals": 6, + "logoUrl": "https://coin-images.coingecko.com/coins/images/66647/large/Coinbase_Wrapped_Ada_%28cbADA%29.png?1750129533", + "priceUsd": "0.6119063256662338" + }, + { + "chainId": 8453, + "address": "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf", + "name": "Coinbase Wrapped BTC", + "symbol": "cbBTC", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/40143/standard/cbbtc.webp", + "priceUsd": "109583" + }, + { + "chainId": 8453, + "address": "0xcbD06E5A2B0C65597161de254AA074E489dEb510", + "name": "Coinbase Wrapped DOGE", + "symbol": "CBDOGE", + "decimals": 8, + "logoUrl": "https://coin-images.coingecko.com/coins/images/66268/large/Coinbase_Wrapped_Doge_%28cbDOGE%29.png?1749023465", + "priceUsd": "0.185795" + }, + { + "chainId": 8453, + "address": "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", + "name": "Coinbase Wrapped Staked ETH", + "symbol": "cbETH", + "decimals": 18, + "logoUrl": "https://ethereum-optimism.github.io/data/cbETH/logo.svg", + "priceUsd": "4228.87" + }, + { + "chainId": 8453, + "address": "0xcb17C9Db87B595717C857a08468793f5bAb6445F", + "name": "Coinbase Wrapped LTC", + "symbol": "cbLTC", + "decimals": 8, + "logoUrl": "https://coin-images.coingecko.com/coins/images/66646/large/Coinbase_Wrapped_Litecoin_%28cbLTC%29.png?1750129508", + "priceUsd": "94.96502154320478" + }, + { + "chainId": 8453, + "address": "0xcb585250f852C6c6bf90434AB21A00f02833a4af", + "name": "Coinbase Wrapped XRP", + "symbol": "cbXRP", + "decimals": 6, + "logoUrl": "https://coin-images.coingecko.com/coins/images/66267/large/Coinbase_Wrapped_XPR_%28cbXRP%29.png?1749023398", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0x1bc0c42215582d5A085795f4baDbaC3ff36d1Bcb", + "name": "tokenbot", + "symbol": "CLANKER", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/51440/large/CLANKER.png?1731232869", + "priceUsd": "106.49" + }, + { + "chainId": 8453, + "address": "0x9e1028F5F1D5eDE59748FFceE5532509976840E0", + "name": "Compound", + "symbol": "COMP", + "decimals": 18, + "logoUrl": "https://ethereum-optimism.github.io/data/COMP/logo.svg", + "priceUsd": "34.87130998995957" + }, + { + "chainId": 8453, + "address": "0xC0041EF357B183448B235a8Ea73Ce4E4eC8c265F", + "name": "Cookie", + "symbol": "COOKIE", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/38450/large/cookie_token_logo_200x200.png?1733194528", + "priceUsd": "0.082198" + }, + { + "chainId": 8453, + "address": "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb", + "name": "Dai Stablecoin", + "symbol": "DAI", + "decimals": 18, + "logoUrl": "https://ethereum-optimism.github.io/data/DAI/logo.svg", + "priceUsd": "0.999454" + }, + { + "chainId": 8453, + "address": "0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed", + "name": "Degen", + "symbol": "DEGEN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/34515/large/android-chrome-512x512.png?1706198225", + "priceUsd": "0.00188454" + }, + { + "chainId": 8453, + "address": "0x6921B130D297cc43754afba22e5EAc0FBf8Db75b", + "name": "doginme", + "symbol": "doginme", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/35123/large/doginme-logo1-transparent200.png?1710856784", + "priceUsd": "0.00034109" + }, + { + "chainId": 8453, + "address": "0x9d0E8f5b25384C7310CB8C6aE32C8fbeb645d083", + "name": "Derive", + "symbol": "DRV", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/52889/large/Token_Logo.png?1734601695", + "priceUsd": "0.03385094" + }, + { + "chainId": 8453, + "address": "0xED6E000dEF95780fb89734c07EE2ce9F6dcAf110", + "name": "Definitive", + "symbol": "EDGE", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/55072/large/EDGE-120x120.png?1743598652", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42", + "name": "EURC", + "symbol": "EURC", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/26045/standard/euro.png", + "priceUsd": "1.15" + }, + { + "chainId": 8453, + "address": "0xb33Ff54b9F7242EF1593d2C9Bcd8f9df46c77935", + "name": "FAI", + "symbol": "FAI", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/52315/large/FAI.png?1733076295", + "priceUsd": "0.00701114" + }, + { + "chainId": 8453, + "address": "0x5aB3D4c385B400F3aBB49e80DE2fAF6a88A7B691", + "name": "Flock", + "symbol": "FLOCK", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/53178/large/FLock_Token_Logo.png?1735561398", + "priceUsd": "0.229223" + }, + { + "chainId": 8453, + "address": "0xB78e7D4C5d47Af92942321eD40419dab0E573810", + "name": "Goldfinch", + "symbol": "GFI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19081/thumb/GOLDFINCH.png?1634369662", + "priceUsd": "0.3759644261757583" + }, + { + "chainId": 8453, + "address": "0xcD2F22236DD9Dfe2356D7C543161D4d260FD9BcB", + "name": "Aavegotchi", + "symbol": "GHST", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12467/thumb/ghst_200.png?1600750321", + "priceUsd": "0.294162" + }, + { + "chainId": 8453, + "address": "0x0F4d237B09Cb37d207BA60353Dc254d4530D4dF1", + "name": "The Graph", + "symbol": "GRT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13397/thumb/Graph_Token.png?1608145566", + "priceUsd": "0.06229674291931587" + }, + { + "chainId": 8453, + "address": "0x4BfAa776991E85e5f8b1255461cbbd216cFc714f", + "name": "HOME", + "symbol": "HOME", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/54873/large/defi-app.png?1742235743", + "priceUsd": "0.02148122" + }, + { + "chainId": 8453, + "address": "0xBCBAf311ceC8a4EAC0430193A528d9FF27ae38C1", + "name": "IoTeX", + "symbol": "IOTX", + "decimals": 18, + "logoUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/2777.png", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0xFf9957816c813C5Ad0b9881A8990Df1E3AA2a057", + "name": "Geojam", + "symbol": "JAM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24648/thumb/ey40AzBN_400x400.jpg?1648507272", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0x98d0baa52b2D063E780DE12F615f963Fe8537553", + "name": "KAITO", + "symbol": "KAITO", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/54411/large/Qm4DW488_400x400.jpg?1739552780", + "priceUsd": "0.996768" + }, + { + "chainId": 8453, + "address": "0x9a26F5433671751C3276a065f57e5a02D2817973", + "name": "Keyboard Cat", + "symbol": "KEYCAT", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/36608/large/keyboard_cat.jpeg?1711965348", + "priceUsd": "0.00191851" + }, + { + "chainId": 8453, + "address": "0x7300B37DfdfAb110d83290A29DfB31B1740219fE", + "name": "Mamo", + "symbol": "MAMO", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/55958/large/Mamo_Circle_200x200_TransBG.png?1748974093", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0xca73ed1815e5915489570014e024b7EbE65dE679", + "name": "Odos Token", + "symbol": "ODOS", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/52914/large/odos.jpg?1734678948", + "priceUsd": "0.00342761" + }, + { + "chainId": 8453, + "address": "0x7002458B1DF59EccB57387bC79fFc7C29E22e6f7", + "name": "Origin Protocol", + "symbol": "OGN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3296/thumb/op.jpg?1547037878", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0xA99F6e6785Da0F5d6fB42495Fe424BCE029Eeb3E", + "name": "Pendle", + "symbol": "PENDLE", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/15069/large/Pendle_Logo_Normal-03.png?1696514728", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0xB4fDe59a779991bfB6a52253B51947828b982be3", + "name": "Pepe", + "symbol": "PEPE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/29850/large/pepe-token.jpeg?1682922725", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0xCD6dDDa305955AcD6b94b934f057E8b0daaD58dE", + "name": "Perpetual Protocol", + "symbol": "PERP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771", + "priceUsd": "0.6380761105790625" + }, + { + "chainId": 8453, + "address": "0xfA980cEd6895AC314E7dE34Ef1bFAE90a5AdD21b", + "name": "Prime", + "symbol": "PRIME", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/29053/large/PRIMELOGOOO.png?1676976222", + "priceUsd": "1.028" + }, + { + "chainId": 8453, + "address": "0x30c7235866872213F68cb1F08c37Cb9eCCB93452", + "name": "Prompt", + "symbol": "PROMPT", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/55169/large/wayfinder.jpg?1744336900", + "priceUsd": "0.077929" + }, + { + "chainId": 8453, + "address": "0xFbB75A59193A3525a8825BeBe7D4b56899E2f7e1", + "name": "ResearchCoin", + "symbol": "RSC", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/28146/large/RH_BOTTLE_CLEAN_Aug_2024_1.png?1732742001", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0xaB36452DbAC151bE02b16Ca17d8919826072f64a", + "name": "Reserve Rights", + "symbol": "RSR", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/8365/large/RSR_Blue_Circle_1000.png?1721777856", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0xC729777d0470F30612B1564Fd96E8Dd26f5814E3", + "name": "Sapien", + "symbol": "SAPIEN", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/68423/large/logo.png?1755710030", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0x1C7a460413dD4e964f96D8dFC56E7223cE88CD85", + "name": "Seamlesss", + "symbol": "SEAM", + "decimals": 18, + "logoUrl": "https://basescan.org/token/images/seamless_32.png", + "priceUsd": "0.228054" + }, + { + "chainId": 8453, + "address": "0x50dA645f148798F68EF2d7dB7C1CB22A6819bb2C", + "name": "SPX6900", + "symbol": "SPX", + "decimals": 8, + "logoUrl": "https://coin-images.coingecko.com/coins/images/31401/large/sticker_(1).jpg?1702371083", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b", + "name": "tBTC", + "symbol": "tBTC", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/uniswap/assets/master/blockchains/ethereum/assets/0x18084fbA666a33d37592fA2633fD49a74DD93a88/logo.png", + "priceUsd": "109597" + }, + { + "chainId": 8453, + "address": "0xAC1Bd2486aAf3B5C0fc3Fd868558b082a531B2B4", + "name": "Toshi", + "symbol": "TOSHI", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/31126/large/Toshi_Logo_-_Circular.png?1721677476", + "priceUsd": "0.00070627" + }, + { + "chainId": 8453, + "address": "0x00000000A22C618fd6b4D7E9A335C4B96B189a38", + "name": "Towns", + "symbol": "TOWNS", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/55230/large/yImUvwK__400x400.png?1744857671", + "priceUsd": "0.01058688" + }, + { + "chainId": 8453, + "address": "0xA81a52B4dda010896cDd386C7fBdc5CDc835ba23", + "name": "OriginTrail", + "symbol": "TRAC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1877/thumb/TRAC.jpg?1635134367", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0xF8e9E61FFB2b491f7DF29823a76009743671CD96", + "name": "Tellor", + "symbol": "TRB", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9644/thumb/Blk_icon_current.png?1584980686", + "priceUsd": "25.203805869310937" + }, + { + "chainId": 8453, + "address": "0xc3De830EA07524a0761646a6a4e4be0e114a3C83", + "name": "Uniswap", + "symbol": "UNI", + "decimals": 18, + "logoUrl": "ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA", + "name": "USD Base Coin", + "symbol": "USDbC", + "decimals": 6, + "logoUrl": "https://ethereum-optimism.github.io/data/USDC/logo.png", + "priceUsd": "0.998565" + }, + { + "chainId": 8453, + "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "name": "USD Coin", + "symbol": "USDC", + "decimals": 6, + "logoUrl": "https://ethereum-optimism.github.io/data/USDC/logo.png", + "priceUsd": "0.999803" + }, + { + "chainId": 8453, + "address": "0xacfE6019Ed1A7Dc6f7B508C02d1b04ec88cC21bf", + "name": "Venice Token", + "symbol": "VVV", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/54023/standard/Venice_Token_(1).png?1738017546", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0xeF4461891DfB3AC8572cCf7C794664A8DD927945", + "name": "WalletConnect Token", + "symbol": "WCT", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/50390/large/wc-token1.png?1727569464", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0xA88594D404727625A9437C3f886C7643872296AE", + "name": "Moonwell", + "symbol": "WELL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/26133/large/WELL.png?1696525221", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0x4200000000000000000000000000000000000006", + "name": "Wrapped Ether", + "symbol": "WETH", + "decimals": 18, + "logoUrl": "https://ethereum-optimism.github.io/data/WETH/logo.png", + "priceUsd": "3847.53" + }, + { + "chainId": 8453, + "address": "0xf43eB8De897Fbc7F2502483B2Bef7Bb9EA179229", + "name": "Horizen", + "symbol": "ZEN", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/691/large/Horizen2.0-logo_icon-on-yellow_%281%29.png?1751696763", + "priceUsd": null + }, + { + "chainId": 8453, + "address": "0x1111111111166b7FE7bd91427724B487980aFc69", + "name": "Zora", + "symbol": "ZORA", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/54693/large/zora.jpg?1741094751", + "priceUsd": "0.071063" + }, + { + "chainId": 8453, + "address": "0x6985884C4392D348587B19cb9eAAf157F13271cd", + "name": "LayerZero", + "symbol": "ZRO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208", + "priceUsd": "1.54" + }, + { + "chainId": 8453, + "address": "0x3bB4445D30AC020a84c1b5A8A2C6248ebC9779D0", + "name": "0x Protocol Token", + "symbol": "ZRX", + "decimals": 18, + "logoUrl": "https://ethereum-optimism.github.io/data/ZRX/logo.png", + "priceUsd": null + }, + { + "chainId": 42161, + "address": "0x6314C31A7a1652cE482cffe247E9CB7c3f4BB9aF", + "name": "1inch", + "symbol": "1INCH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028", + "priceUsd": "0.5666056336426988" + }, + { + "chainId": 42161, + "address": "0xba5DdD1f9d7F570dc94a51479a000E3BCE967196", + "name": "Aave", + "symbol": "AAVE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110", + "priceUsd": "218.02" + }, + { + "chainId": 42161, + "address": "0x53691596d1BCe8CEa565b84d4915e69e03d9C99d", + "name": "Across Protocol Token", + "symbol": "ACX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/28161/large/across-200x200.png?1696527165", + "priceUsd": "0.18178439053111223" + }, + { + "chainId": 42161, + "address": "0x377c1Fc73D4D0f5600cd943776CED07c2B9783cd", + "name": "Aevo", + "symbol": "AEVO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/35893/standard/aevo.png", + "priceUsd": "0.05803568605229448" + }, + { + "chainId": 42161, + "address": "0xFA5Ed56A203466CbBC2430a43c66b9D8723528E7", + "name": "agEur", + "symbol": "agEUR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19479/standard/agEUR.png?1696518915", + "priceUsd": "1.15" + }, + { + "chainId": 42161, + "address": "0xb7910E8b16e63EFD51d5D1a093d56280012A3B9C", + "name": "Adventure Gold", + "symbol": "AGLD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/18125/thumb/lpgblc4h_400x400.jpg?1630570955", + "priceUsd": "0.3734" + }, + { + "chainId": 42161, + "address": "0xeC76E8fe6e2242e6c2117caA244B9e2DE1569923", + "name": "AIOZ Network", + "symbol": "AIOZ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14631/thumb/aioz_logo.png?1617413126", + "priceUsd": "0.17842825104177942" + }, + { + "chainId": 42161, + "address": "0xe7dcD50836d0A28c959c72D72122fEDB8E245A6C", + "name": "Aleph im", + "symbol": "ALEPH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11676/thumb/Monochram-aleph.png?1608483725", + "priceUsd": "0.05698747574531833" + }, + { + "chainId": 42161, + "address": "0xeF6124368c0B56556667e0de77eA008DfC0a71d1", + "name": "Alethea Artificial Liquid Intelligence", + "symbol": "ALI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/22062/thumb/alethea-logo-transparent-colored.png?1642748848", + "priceUsd": "0.0037820408772880044" + }, + { + "chainId": 42161, + "address": "0xC9CBf102c73fb77Ec14f8B4C8bd88e050a6b2646", + "name": "Alpha Venture DAO", + "symbol": "ALPHA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12738/thumb/AlphaToken_256x256.png?1617160876", + "priceUsd": "0.009244468667224339" + }, + { + "chainId": 42161, + "address": "0x1bfc5d35bf0f7B9e15dc24c78b8C02dbC1e95447", + "name": "Ankr", + "symbol": "ANKR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4324/thumb/U85xTl2.png?1608111978", + "priceUsd": "0.009591310941942334" + }, + { + "chainId": 42161, + "address": "0x74885b4D524d497261259B38900f54e6dbAd2210", + "name": "ApeCoin", + "symbol": "APE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24383/small/apecoin.jpg?1647476455", + "priceUsd": "0.4175570330025673" + }, + { + "chainId": 42161, + "address": "0xF01dB12F50D0CDF5Fe360ae005b9c52F92CA7811", + "name": "API3", + "symbol": "API3", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13256/thumb/api3.jpg?1606751424", + "priceUsd": "0.6800993237866327" + }, + { + "chainId": 42161, + "address": "0x912CE59144191C1204E64559FE8253a0e49E6548", + "name": "Arbitrum", + "symbol": "ARB", + "decimals": 18, + "logoUrl": "https://arbitrum.foundation/logo.png", + "priceUsd": "0.295531" + }, + { + "chainId": 42161, + "address": "0xDac5094B7D59647626444a4F905060FCda4E656E", + "name": "Arkham", + "symbol": "ARKM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/30929/standard/Arkham_Logo_CG.png?1696529771", + "priceUsd": "0.3227787389603748" + }, + { + "chainId": 42161, + "address": "0xAC9Ac2C17cdFED4AbC80A53c5553388575714d03", + "name": "Automata", + "symbol": "ATA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15985/thumb/ATA.jpg?1622535745", + "priceUsd": "0.0261" + }, + { + "chainId": 42161, + "address": "0xc7dEf82Ba77BAF30BbBc9b6162DC075b49092fb4", + "name": "Aethir Token", + "symbol": "ATH", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/36179/large/logogram_circle_dark_green_vb_green_(1).png?1718232706", + "priceUsd": "0.026847097648645523" + }, + { + "chainId": 42161, + "address": "0x23ee2343B892b1BB63503a4FAbc840E0e2C6810f", + "name": "Axelar", + "symbol": "AXL", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/27277/large/V-65_xQ1_400x400.jpeg", + "priceUsd": "0.39376735361624743" + }, + { + "chainId": 42161, + "address": "0xe88998Fb579266628aF6a03e3821d5983e5D0089", + "name": "Axie Infinity", + "symbol": "AXS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13029/thumb/axie_infinity_logo.png?1604471082", + "priceUsd": "1.449771531801153" + }, + { + "chainId": 42161, + "address": "0xBfa641051Ba0a0Ad1b0AcF549a89536A0D76472E", + "name": "Badger DAO", + "symbol": "BADGER", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13287/thumb/badger_dao_logo.jpg?1607054976", + "priceUsd": "0.754969599073009" + }, + { + "chainId": 42161, + "address": "0x040d1EdC9569d4Bab2D15287Dc5A4F10F56a56B8", + "name": "Balancer", + "symbol": "BAL", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xba100000625a3754423978a60c9317c58a424e3D/logo.png", + "priceUsd": "0.9403628441818892" + }, + { + "chainId": 42161, + "address": "0x3450687EF141dCd6110b77c2DC44B008616AeE75", + "name": "Basic Attention Token", + "symbol": "BAT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/677/thumb/basic-attention-token.png?1547034427", + "priceUsd": "0.3049273553844044" + }, + { + "chainId": 42161, + "address": "0xa68Ec98D7ca870cF1Dd0b00EBbb7c4bF60A8e74d", + "name": "Biconomy", + "symbol": "BICO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/21061/thumb/biconomy_logo.jpg?1638269749", + "priceUsd": "0.8040113171836386" + }, + { + "chainId": 42161, + "address": "0x406C8dB506653D882295875F633bEC0bEb921C2A", + "name": "BitDAO", + "symbol": "BIT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17627/thumb/rI_YptK8.png?1653983088", + "priceUsd": "1.4606179360356102" + }, + { + "chainId": 42161, + "address": "0xf7e17BA61973bcDB61f471eFb989E47d13bD565D", + "name": "HarryPotterObamaSonic10Inu", + "symbol": "BITCOIN", + "decimals": 8, + "logoUrl": "https://coin-images.coingecko.com/coins/images/30323/large/hpos10i_logo_casino_night-dexview.png?1696529224", + "priceUsd": "782620.5761437613" + }, + { + "chainId": 42161, + "address": "0xEf171a5BA71348eff16616fd692855c2Fe606EB2", + "name": "Blur", + "symbol": "BLUR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/28453/large/blur.png?1670745921", + "priceUsd": "0.16351842625932533" + }, + { + "chainId": 42161, + "address": "0x7A24159672b83ED1b89467c9d6A99556bA06D073", + "name": "Bancor Network Token", + "symbol": "BNT", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C/logo.png", + "priceUsd": "0.576" + }, + { + "chainId": 42161, + "address": "0x0D81E50bC677fa67341c44D7eaA9228DEE64A4e1", + "name": "BarnBridge", + "symbol": "BOND", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12811/thumb/barnbridge.jpg?1602728853", + "priceUsd": "0.121968" + }, + { + "chainId": 42161, + "address": "0x31190254504622cEFdFA55a7d3d272e6462629a2", + "name": "Binance USD", + "symbol": "BUSD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766", + "priceUsd": "0.9997010901104858" + }, + { + "chainId": 42161, + "address": "0xCdc343ebf71e38F003eD6c80171F5B8D7cF58860", + "name": "PancakeSwap", + "symbol": "CAKE", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/12632/large/pancakeswap-cake-logo_%281%29.png?1696512440", + "priceUsd": "2.414" + }, + { + "chainId": 42161, + "address": "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf", + "name": "Coinbase Wrapped BTC", + "symbol": "cbBTC", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/40143/large/cbbtc.webp", + "priceUsd": null + }, + { + "chainId": 42161, + "address": "0x1DEBd73E752bEaF79865Fd6446b0c970EaE7732f", + "name": "Coinbase Wrapped Staked ETH", + "symbol": "cbETH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/27008/large/cbeth.png", + "priceUsd": "4242.730114917522" + }, + { + "chainId": 42161, + "address": "0x4E51aC49bC5e2d87e0EF713E9e5AB2D71EF4F336", + "name": "Celo native asset (Wormhole)", + "symbol": "CELO", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/wormhole-foundation/wormhole-token-list/main/assets/celo_wh.png", + "priceUsd": null + }, + { + "chainId": 42161, + "address": "0x3a8B787f78D775AECFEEa15706D4221B40F345AB", + "name": "Celer Network", + "symbol": "CELR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4379/thumb/Celr.png?1554705437", + "priceUsd": "0.00533778" + }, + { + "chainId": 42161, + "address": "0x354A6dA3fcde098F8389cad84b0182725c6C91dE", + "name": "Compound", + "symbol": "COMP", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png", + "priceUsd": "34.892352158571896" + }, + { + "chainId": 42161, + "address": "0x6FE14d3CC2f7bDdffBa5CdB3BBE7467dd81ea101", + "name": "COTI", + "symbol": "COTI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2962/thumb/Coti.png?1559653863", + "priceUsd": "0.03138282674043112" + }, + { + "chainId": 42161, + "address": "0xcb8b5CD20BdCaea9a010aC1F8d835824F5C87A04", + "name": "CoW Protocol", + "symbol": "COW", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24384/large/CoW-token_logo.png?1719524382", + "priceUsd": "0.21883663121043434" + }, + { + "chainId": 42161, + "address": "0x69b937dB799a9BECC9E8A6F0a5d36eA3657273bf", + "name": "Covalent", + "symbol": "CQT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14168/thumb/covalent-cqt.png?1624545218", + "priceUsd": null + }, + { + "chainId": 42161, + "address": "0x8ea3156f834A0dfC78F1A5304fAC2CdA676F354C", + "name": "Cronos", + "symbol": "CRO", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/7310/thumb/oCw2s3GI_400x400.jpeg?1645172042", + "priceUsd": "0.14617748677369224" + }, + { + "chainId": 42161, + "address": "0x11cDb42B0EB46D95f990BeDD4695A6e3fA034978", + "name": "Curve DAO Token", + "symbol": "CRV", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xD533a949740bb3306d119CC777fa900bA034cd52/logo.png", + "priceUsd": "0.488167" + }, + { + "chainId": 42161, + "address": "0x319f865b287fCC10b30d8cE6144e8b6D1b476999", + "name": "Cartesi", + "symbol": "CTSI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021", + "priceUsd": "0.04840133" + }, + { + "chainId": 42161, + "address": "0x84F5c2cFba754E76DD5aE4fB369CfC920425E12b", + "name": "Cryptex Finance", + "symbol": "CTX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14932/thumb/glossy_icon_-_C200px.png?1619073171", + "priceUsd": "1.011059556891287" + }, + { + "chainId": 42161, + "address": "0x9DfFB23CAd3322440bCcFF7aB1C58E781dDBF144", + "name": "Civic", + "symbol": "CVC", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/788/thumb/civic.png?1547034556", + "priceUsd": "0.05808500247923828" + }, + { + "chainId": 42161, + "address": "0xaAFcFD42c9954C6689ef1901e03db742520829c5", + "name": "Convex Finance", + "symbol": "CVX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15585/thumb/convex.png?1621256328", + "priceUsd": "2.2510641459003726" + }, + { + "chainId": 42161, + "address": "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1", + "name": "Dai Stablecoin", + "symbol": "DAI", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png", + "priceUsd": "0.998653" + }, + { + "chainId": 42161, + "address": "0x3Be7cB2e9413Ef8F42b4A202a0114EB59b64e227", + "name": "DexTools", + "symbol": "DEXT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11603/thumb/dext.png?1605790188", + "priceUsd": "0.3163773789298991" + }, + { + "chainId": 42161, + "address": "0xca642467C6Ebe58c13cB4A7091317f34E17ac05e", + "name": "DIA", + "symbol": "DIA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11955/thumb/image.png?1646041751", + "priceUsd": "0.5454684863938065" + }, + { + "chainId": 42161, + "address": "0xE3696a02b2C9557639E29d829E9C45EFa49aD47A", + "name": "district0x", + "symbol": "DNT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/849/thumb/district0x.png?1547223762", + "priceUsd": "0.018998360889542917" + }, + { + "chainId": 42161, + "address": "0x4667cf53C4eDF659E402B733BEA42B18B68dd74c", + "name": "DeFi Pulse Index", + "symbol": "DPI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12465/thumb/defi_pulse_index_set.png?1600051053", + "priceUsd": "78.78085039165822" + }, + { + "chainId": 42161, + "address": "0x77b7787a09818502305C95d68A2571F090abb135", + "name": "Derive", + "symbol": "DRV", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/52889/large/Token_Logo.png?1734601695", + "priceUsd": "0.03385814" + }, + { + "chainId": 42161, + "address": "0x51863cB90Ce5d6dA9663106F292fA27c8CC90c5a", + "name": "dYdX", + "symbol": "DYDX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17500/thumb/hjnIm9bV.jpg?1628009360", + "priceUsd": "0.3064" + }, + { + "chainId": 42161, + "address": "0x606C3e5075e5555e79Aa15F1E9FACB776F96C248", + "name": "EigenLayer", + "symbol": "EIGEN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/37441/large/eigen.jpg?1728023974", + "priceUsd": "1.0061515731779997" + }, + { + "chainId": 42161, + "address": "0x3e4Cff6E50F37F731284A92d44AE943e17077fD4", + "name": "Dogelon Mars", + "symbol": "ELON", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14962/thumb/6GxcPRo3_400x400.jpg?1619157413", + "priceUsd": null + }, + { + "chainId": 42161, + "address": "0xdf8F0c63D9335A0AbD89F9F752d293A98EA977d8", + "name": "Ethena", + "symbol": "ENA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/36530/standard/ethena.png", + "priceUsd": "0.39949582364488667" + }, + { + "chainId": 42161, + "address": "0x7fa9549791EFc9030e1Ed3F25D18014163806758", + "name": "Enjin Coin", + "symbol": "ENJ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1102/thumb/enjin-coin-logo.png?1547035078", + "priceUsd": "0.05399580550182594" + }, + { + "chainId": 42161, + "address": "0xfeA31d704DEb0975dA8e77Bf13E04239e70d7c28", + "name": "Ethereum Name Service", + "symbol": "ENS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/19785/thumb/acatxTm8_400x400.jpg?1635850140", + "priceUsd": "6.267815979236216" + }, + { + "chainId": 42161, + "address": "0x2354c8e9Ea898c751F1A15Addeb048714D667f96", + "name": "Ethernity Chain", + "symbol": "ERN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14238/thumb/LOGO_HIGH_QUALITY.png?1647831402", + "priceUsd": "0.06481013502586307" + }, + { + "chainId": 42161, + "address": "0x07D65C18CECbA423298c0aEB5d2BeDED4DFd5736", + "name": "Ether.fi", + "symbol": "ETHFI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/35958/standard/etherfi.jpeg", + "priceUsd": "0.9457118455139375" + }, + { + "chainId": 42161, + "address": "0x863708032B5c328e11aBcbC0DF9D79C71Fc52a48", + "name": "Euro Coin", + "symbol": "EURC", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/26045/thumb/euro-coin.png?1655394420", + "priceUsd": "1.0890138397307085" + }, + { + "chainId": 42161, + "address": "0x8553d254Cb6934b16F87D2e486b64BbD24C83C70", + "name": "Harvest Finance", + "symbol": "FARM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12304/thumb/Harvest.png?1613016180", + "priceUsd": "55.17330979173209" + }, + { + "chainId": 42161, + "address": "0x4BE87C766A7CE11D5Cc864b6C3Abb7457dCC4cC9", + "name": "Fetch ai", + "symbol": "FET", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/5681/thumb/Fetch.jpg?1572098136", + "priceUsd": "0.2639005378396266" + }, + { + "chainId": 42161, + "address": "0x849B40AB2469309117Ed1038c5A99894767C7282", + "name": "Stafi", + "symbol": "FIS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12423/thumb/stafi_logo.jpg?1599730991", + "priceUsd": "0.029255617075697782" + }, + { + "chainId": 42161, + "address": "0xA8C25FdC09763A176353CC6a76882e05b4905FAe", + "name": "FLOKI", + "symbol": "FLOKI", + "decimals": 9, + "logoUrl": "https://assets.coingecko.com/coins/images/16746/standard/PNG_image.png?1696516318", + "priceUsd": null + }, + { + "chainId": 42161, + "address": "0x63806C056Fa458c548Fb416B15E358A9D685710A", + "name": "Flux", + "symbol": "FLUX", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x720CD16b011b987Da3518fbf38c3071d4F0D1495/logo.png", + "priceUsd": "0.10776845502533644" + }, + { + "chainId": 42161, + "address": "0x3A1429d50E0cBBc45c997aF600541Fe1cc3D2923", + "name": "Forta", + "symbol": "FORT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/25060/thumb/Forta_lgo_%281%29.png?1655353696", + "priceUsd": "0.0339980846493792" + }, + { + "chainId": 42161, + "address": "0xf929de51D91C77E42f5090069E0AD7A09e513c73", + "name": "ShapeShift FOX Token", + "symbol": "FOX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9988/thumb/FOX.png?1574330622", + "priceUsd": "0.017904621983385705" + }, + { + "chainId": 42161, + "address": "0x7468a5d8E02245B00E8C0217fCE021C70Bc51305", + "name": "Frax", + "symbol": "FRAX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13422/thumb/frax_logo.png?1608476506", + "priceUsd": "0.9953925999394807" + }, + { + "chainId": 42161, + "address": "0xd42785D323e608B9E99fa542bd8b1000D4c2Df37", + "name": "Fantom", + "symbol": "FTM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4001/thumb/Fantom.png?1558015016", + "priceUsd": "0.14926604510359207" + }, + { + "chainId": 42161, + "address": "0xd9f9d2Ee2d3EFE420699079f16D9e924affFdEA4", + "name": "Frax Share", + "symbol": "FXS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13423/thumb/frax_share.png?1608478989", + "priceUsd": "1.304" + }, + { + "chainId": 42161, + "address": "0xc27E7325a6BEA1FcC06de7941473f5279bfd1182", + "name": "Galxe", + "symbol": "GAL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24530/thumb/GAL-Token-Icon.png?1651483533", + "priceUsd": "0.38293516983527515" + }, + { + "chainId": 42161, + "address": "0x2A676eeAd159c4C8e8593471c6d666F02827FF8C", + "name": "GALA", + "symbol": "GALA", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/12493/standard/GALA-COINGECKO.png?1696512310", + "priceUsd": "0.010105070396642109" + }, + { + "chainId": 42161, + "address": "0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a", + "name": "GMX", + "symbol": "GMX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/18323/large/arbit.png?1631532468", + "priceUsd": "9.74" + }, + { + "chainId": 42161, + "address": "0xa0b862F60edEf4452F25B4160F177db44DeB6Cf1", + "name": "Gnosis Token", + "symbol": "GNO", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6810e776880C02933D47DB1b9fc05908e5386b96/logo.png", + "priceUsd": "93.86412930923497" + }, + { + "chainId": 42161, + "address": "0x9623063377AD1B27544C965cCd7342f7EA7e88C7", + "name": "The Graph", + "symbol": "GRT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13397/thumb/Graph_Token.png?1608145566", + "priceUsd": "0.061879" + }, + { + "chainId": 42161, + "address": "0x7f9a7DB853Ca816B9A138AEe3380Ef34c437dEe0", + "name": "Gitcoin", + "symbol": "GTC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15810/thumb/gitcoin.png?1621992929", + "priceUsd": "0.18623683715954772" + }, + { + "chainId": 42161, + "address": "0x589d35656641d6aB57A545F08cf473eCD9B6D5F7", + "name": "GYEN", + "symbol": "GYEN", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/14191/thumb/icon_gyen_200_200.png?1614843343", + "priceUsd": "0.00562604" + }, + { + "chainId": 42161, + "address": "0xd12Eeb0142D4Efe7Af82e4f29E5Af382615bcEeA", + "name": "Highstreet", + "symbol": "HIGH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/18973/thumb/logosq200200Coingecko.png?1634090470", + "priceUsd": "0.28957222132721055" + }, + { + "chainId": 42161, + "address": "0x177F394A3eD18FAa85c1462Ae626438a70294EF7", + "name": "HOPR", + "symbol": "HOPR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14061/thumb/Shared_HOPR_logo_512px.png?1614073468", + "priceUsd": "0.04094832557762472" + }, + { + "chainId": 42161, + "address": "0x61cA9D186f6b9a793BC08F6C79fd35f205488673", + "name": "Illuvium", + "symbol": "ILV", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14468/large/ILV.JPG", + "priceUsd": "10.669895049348813" + }, + { + "chainId": 42161, + "address": "0x3cFD99593a7F035F717142095a3898e3Fca7783e", + "name": "Immutable X", + "symbol": "IMX", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/17233/thumb/imx.png?1636691817", + "priceUsd": "3.927139943274612" + }, + { + "chainId": 42161, + "address": "0x2A2053cb633CAD465B4A8975eD3d7f09DF608F80", + "name": "Injective", + "symbol": "INJ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12882/thumb/Secondary_Symbol.png?1628233237", + "priceUsd": "7.702773716932627" + }, + { + "chainId": 42161, + "address": "0x25f05699548D3A0820b99f93c10c8BB573E27083", + "name": "JasmyCoin", + "symbol": "JASMY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13876/thumb/JASMY200x200.jpg?1612473259", + "priceUsd": "0.0100340007431409" + }, + { + "chainId": 42161, + "address": "0x010700AB046Dd8e92b0e3587842080Df36364ed3", + "name": "Kinto", + "symbol": "K", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/54964/standard/k200.png?1742894885", + "priceUsd": "0.003152270826321105" + }, + { + "chainId": 42161, + "address": "0xf75eE6D319741057a82a88Eeff1DbAFAB7307b69", + "name": "KRYLL", + "symbol": "KRL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2807/thumb/krl.png?1547036979", + "priceUsd": "0.250686" + }, + { + "chainId": 42161, + "address": "0x3A18dcC9745eDcD1Ef33ecB93b0b6eBA5671e7Ca", + "name": "Kujira", + "symbol": "KUJI", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/20685/standard/kuji-200x200.png", + "priceUsd": null + }, + { + "chainId": 42161, + "address": "0x13Ad51ed4F1B7e9Dc168d8a00cB3f4dDD85EfA60", + "name": "Lido DAO", + "symbol": "LDO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13573/thumb/Lido_DAO.png?1609873644", + "priceUsd": "0.864329" + }, + { + "chainId": 42161, + "address": "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4", + "name": "ChainLink Token", + "symbol": "LINK", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png", + "priceUsd": "17.15" + }, + { + "chainId": 42161, + "address": "0x349fc93da004a63F3B1343361465981330A40B25", + "name": "Litentry", + "symbol": "LIT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13825/large/logo_200x200.png", + "priceUsd": "0.3308437945098985" + }, + { + "chainId": 42161, + "address": "0x289ba1701C2F088cf0faf8B3705246331cB8A839", + "name": "Livepeer", + "symbol": "LPT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/7137/thumb/logo-circle-green.png?1619593365", + "priceUsd": "4.69" + }, + { + "chainId": 42161, + "address": "0xfb9E5D956D889D91a82737B9bFCDaC1DCE3e1449", + "name": "Liquity", + "symbol": "LQTY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14665/thumb/200-lqty-icon.png?1617631180", + "priceUsd": "0.576187524157741" + }, + { + "chainId": 42161, + "address": "0x46d0cE7de6247b0A95f67b43B589b4041BaE7fbE", + "name": "LoopringCoin V2", + "symbol": "LRC", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD/logo.png", + "priceUsd": "0.09168362470576899" + }, + { + "chainId": 42161, + "address": "0x93b346b6BC2548dA6A1E7d98E9a421B42541425b", + "name": "Liquity USD", + "symbol": "LUSD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14666/thumb/Group_3.png?1617631327", + "priceUsd": "1.0123695006427633" + }, + { + "chainId": 42161, + "address": "0x539bdE0d7Dbd336b79148AA742883198BBF60342", + "name": "MAGIC", + "symbol": "MAGIC", + "decimals": 18, + "logoUrl": "https://dynamic-assets.coinbase.com/30320a63f6038b944c9c0202fcb2392e6a1bd333814f74b4674774dd87f2d06d64fdd74c2f1ab4639917c75b749c323450408bec7a2737af8ae0c17871aa90de/asset_icons/98d278cda11639ed7449a0a3086cd2c83937ce71baf4ee43bb5b777423c00a75.png", + "priceUsd": "0.133993" + }, + { + "chainId": 42161, + "address": "0x442d24578A564EF628A65e6a7E3e7be2a165E231", + "name": "Decentraland", + "symbol": "MANA", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/878/thumb/decentraland-mana.png?1550108745", + "priceUsd": "0.22700970866499512" + }, + { + "chainId": 42161, + "address": "0x533A7B414CD1236815a5e09F1E97FC7d5c313739", + "name": "Mask Network", + "symbol": "MASK", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14051/thumb/Mask_Network.jpg?1614050316", + "priceUsd": "0.8146582337479744" + }, + { + "chainId": 42161, + "address": "0x99F40b01BA9C469193B360f72740E416B17Ac332", + "name": "MATH", + "symbol": "MATH", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11335/thumb/2020-05-19-token-200.png?1589940590", + "priceUsd": "0.0640505450190832" + }, + { + "chainId": 42161, + "address": "0x561877b6b3DD7651313794e5F2894B2F18bE0766", + "name": "Polygon", + "symbol": "MATIC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912", + "priceUsd": "0.167356200121039" + }, + { + "chainId": 42161, + "address": "0x7F728F3595db17B0B359f4FC47aE80FAd2e33769", + "name": "Metis", + "symbol": "METIS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15595/thumb/metis.jpeg?1660285312", + "priceUsd": "9.022" + }, + { + "chainId": 42161, + "address": "0xB20A02dfFb172C474BC4bDa3fD6f4eE70C04daf2", + "name": "Magic Internet Money", + "symbol": "MIM", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/16786/thumb/mimlogopng.png?1624979612", + "priceUsd": "131.60724010992877" + }, + { + "chainId": 42161, + "address": "0x2e9a6Df78E42a30712c10a9Dc4b1C8656f8F2879", + "name": "Maker", + "symbol": "MKR", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2/logo.png", + "priceUsd": "1301.5632009621029" + }, + { + "chainId": 42161, + "address": "0x8f5c1A99b1df736Ad685006Cb6ADCA7B7Ae4b514", + "name": "Melon", + "symbol": "MLN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/605/thumb/melon.png?1547034295", + "priceUsd": "6.62" + }, + { + "chainId": 42161, + "address": "0x9c1a1C7bA9c2602123FD7EF3eb41a769edf6C53A", + "name": "Mantle", + "symbol": "MNT", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/30980/large/Mantle-Logo-mark.png?1739213200", + "priceUsd": "1.4616617489221864" + }, + { + "chainId": 42161, + "address": "0x96c42662820F6Ea32f0A61A06a38a72B206aABaC", + "name": "Mog Coin", + "symbol": "MOG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/31059/large/MOG_LOGO_200x200.png", + "priceUsd": null + }, + { + "chainId": 42161, + "address": "0xE390C0B46bd723995BE02640E6F1e1c802F620AC", + "name": "Morpho Token", + "symbol": "MORPHO", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/29837/large/Morpho-token-icon.png?1726771230", + "priceUsd": "1.9916270083212633" + }, + { + "chainId": 42161, + "address": "0x29024832eC3baBF5074D4F46102aA988097f0Ca0", + "name": "Maple", + "symbol": "MPL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14097/thumb/photo_2021-05-03_14.20.41.jpeg?1620022863", + "priceUsd": "0.726915952818" + }, + { + "chainId": 42161, + "address": "0x7b9b94aebe5E2039531af8E31045f377EcD9A39A", + "name": "Multichain", + "symbol": "MULTI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/22087/thumb/1_Wyot-SDGZuxbjdkaOeT2-A.png?1640764238", + "priceUsd": "0.43731768009259314" + }, + { + "chainId": 42161, + "address": "0x5445972E76c5e4CEdD12B6e2BceF69133E15992F", + "name": "GensoKishi Metaverse", + "symbol": "MV", + "decimals": 18, + "logoUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/17704.png", + "priceUsd": "0.00566181" + }, + { + "chainId": 42161, + "address": "0x91b468Fe3dce581D7a6cFE34189F1314b6862eD6", + "name": "MXC", + "symbol": "MXC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/4604/thumb/mxc.png?1655534336", + "priceUsd": "0.001453056192" + }, + { + "chainId": 42161, + "address": "0x53236015A675fcB937485F1AE58040e4Fb920d5b", + "name": "PolySwarm", + "symbol": "NCT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2843/thumb/ImcYCVfX_400x400.jpg?1628519767", + "priceUsd": "0.024243354930807797" + }, + { + "chainId": 42161, + "address": "0xBE06ca305A5Cb49ABf6B1840da7c42690406177b", + "name": "NKN", + "symbol": "NKN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3375/thumb/nkn.png?1548329212", + "priceUsd": "0.018374461975751863" + }, + { + "chainId": 42161, + "address": "0x597701b32553b9fa473e21362D480b3a6B569711", + "name": "Numeraire", + "symbol": "NMR", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671/logo.png", + "priceUsd": "11.757844870568455" + }, + { + "chainId": 42161, + "address": "0x933d31561e470478079FEB9A6Dd2691fAD8234DF", + "name": "Ocean Protocol", + "symbol": "OCEAN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3687/thumb/ocean-protocol-logo.jpg?1547038686", + "priceUsd": "0.3492498983528362" + }, + { + "chainId": 42161, + "address": "0x6FEb262FEb0f775B5312D2e009923f7f58AE423E", + "name": "Origin Protocol", + "symbol": "OGN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3296/thumb/op.jpg?1547037878", + "priceUsd": "0.04557489609519924" + }, + { + "chainId": 42161, + "address": "0xd962C1895c46AC0378C502c207748b7061421e8e", + "name": "OMG Network", + "symbol": "OMG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/776/thumb/OMG_Network.jpg?1591167168", + "priceUsd": "0.11152595800895197" + }, + { + "chainId": 42161, + "address": "0xA2d52A05B8Bead5d824DF54Dd1AA63188B37A5E7", + "name": "Ondo Finance", + "symbol": "ONDO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/26580/standard/ONDO.png?1696525656", + "priceUsd": "0.6950394015835585" + }, + { + "chainId": 42161, + "address": "0x1BDCC2075d5370293E248Cab0173eC3E551e6218", + "name": "Orion Protocol", + "symbol": "ORN", + "decimals": 8, + "logoUrl": "https://assets.coingecko.com/coins/images/11841/thumb/orion_logo.png?1594943318", + "priceUsd": "0.12224884779622926" + }, + { + "chainId": 42161, + "address": "0xfEb4DfC8C4Cf7Ed305bb08065D08eC6ee6728429", + "name": "PAX Gold", + "symbol": "PAXG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9519/thumb/paxg.PNG?1568542565", + "priceUsd": "20915.10356209434" + }, + { + "chainId": 42161, + "address": "0x0c880f6761F1af8d9Aa9C466984b80DAb9a8c9e8", + "name": "Pendle", + "symbol": "PENDLE", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/15069/large/Pendle_Logo_Normal-03.png?1696514728", + "priceUsd": "3.08" + }, + { + "chainId": 42161, + "address": "0x35E6A59F786d9266c7961eA28c7b768B33959cbB", + "name": "Pepe", + "symbol": "PEPE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/29850/large/pepe-token.jpeg?1682922725", + "priceUsd": null + }, + { + "chainId": 42161, + "address": "0x753D224bCf9AAFaCD81558c32341416df61D3DAC", + "name": "Perpetual Protocol", + "symbol": "PERP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771", + "priceUsd": "0.196639" + }, + { + "chainId": 42161, + "address": "0xac7CE9F2794e01c0D27b096C52f592e343D77cbf", + "name": "Pirate Nation", + "symbol": "PIRATE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/38524/standard/_Pirate_Transparent_200x200.png", + "priceUsd": "0.012634903958467211" + }, + { + "chainId": 42161, + "address": "0x044d8e7F3A17751D521efEa8CCf9282268fE08CC", + "name": "Polygon Ecosystem Token", + "symbol": "POL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/32440/large/polygon.png?1698233684", + "priceUsd": "0.18817549157157037" + }, + { + "chainId": 42161, + "address": "0xeeeB5EaC2dB7A7Fc28134aA3248580d48b016b64", + "name": "Polkastarter", + "symbol": "POLS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12648/thumb/polkastarter.png?1609813702", + "priceUsd": "0.13968289083615928" + }, + { + "chainId": 42161, + "address": "0xE12F29704F635F4A6E7Ae154838d21F9B33809e9", + "name": "Polymath", + "symbol": "POLY", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/2784/thumb/inKkF01.png?1605007034", + "priceUsd": "0.09613655976474135" + }, + { + "chainId": 42161, + "address": "0xdA0a57B710768ae17941a9Fa33f8B720c8bD9ddD", + "name": "Marlin", + "symbol": "POND", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/8903/thumb/POND_200x200.png?1622515451", + "priceUsd": "0.00549202" + }, + { + "chainId": 42161, + "address": "0x6380F3d0C1412a80EB00F49064DA30749DB991DE", + "name": "Portal", + "symbol": "PORTAL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/35436/standard/portal.jpeg", + "priceUsd": "0.024390972487010932" + }, + { + "chainId": 42161, + "address": "0x4e91F2AF1ee0F84B529478f19794F5AFD423e4A6", + "name": "Power Ledger", + "symbol": "POWR", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/1104/thumb/power-ledger.png?1547035082", + "priceUsd": "0.5922676472837096" + }, + { + "chainId": 42161, + "address": "0x8d8e1b6ffc6832E8D2eF0DE8a3d957cAE7ac5067", + "name": "Prime", + "symbol": "PRIME", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/29053/large/PRIMELOGOOO.png?1676976222", + "priceUsd": "1.0191423682789338" + }, + { + "chainId": 42161, + "address": "0x82164a8B646401a8776F9dC5c8Cba35DcAf60Cd2", + "name": "PARSIQ", + "symbol": "PRQ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11973/thumb/DsNgK0O.png?1596590280", + "priceUsd": "0.004191303199207259" + }, + { + "chainId": 42161, + "address": "0x327006c8712FE0AbdbbD55B7999DB39b0967342E", + "name": "PayPal USD", + "symbol": "PYUSD", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/31212/large/PYUSD_Logo_%282%29.png?1691458314", + "priceUsd": "0.9997452158938772" + }, + { + "chainId": 42161, + "address": "0xC7557C73e0eCa2E1BF7348bB6874Aee63C7eFF85", + "name": "Quant", + "symbol": "QNT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/3370/thumb/5ZOu7brX_400x400.jpg?1612437252", + "priceUsd": "9646210.964722198" + }, + { + "chainId": 42161, + "address": "0x3c45038f4807c5bb72F6BC72c2A2B9c012155e49", + "name": "Radicle", + "symbol": "RAD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14013/thumb/radicle.png?1614402918", + "priceUsd": "0.4811624602" + }, + { + "chainId": 42161, + "address": "0xaeF5bbcbFa438519a5ea80B4c7181B4E78d419f2", + "name": "Rai Reflex Index", + "symbol": "RAI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14004/thumb/RAI-logo-coin.png?1613592334", + "priceUsd": "4.123940170639339" + }, + { + "chainId": 42161, + "address": "0xCf78572A8fE97b2B9a4B9709f6a7D9a863c1b8E0", + "name": "Rarible", + "symbol": "RARI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11845/thumb/Rari.png?1594946953", + "priceUsd": "0.5689311289689273" + }, + { + "chainId": 42161, + "address": "0x2E9AE8f178d5Ea81970C7799A377B3985cbC335F", + "name": "Rubic", + "symbol": "RBC", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12629/thumb/200x200.png?1607952509", + "priceUsd": null + }, + { + "chainId": 42161, + "address": "0x9fA891e1dB0a6D1eEAC4B929b5AAE1011C79a204", + "name": "Republic Token", + "symbol": "REN", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x408e41876cCCDC0F92210600ef50372656052a38/logo.png", + "priceUsd": "0.005416" + }, + { + "chainId": 42161, + "address": "0x1Cb5bBc64e148C5b889E3c667B49edF78BB92171", + "name": "Request", + "symbol": "REQ", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/1031/thumb/Request_icon_green.png?1643250951", + "priceUsd": "0.12285739557237468" + }, + { + "chainId": 42161, + "address": "0xef888bcA6AB6B1d26dbeC977C455388ecd794794", + "name": "Rari Governance Token", + "symbol": "RGT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12900/thumb/Rari_Logo_Transparent.png?1613978014", + "priceUsd": "0.04800435" + }, + { + "chainId": 42161, + "address": "0xE575586566b02A16338c199c23cA6d295D794e66", + "name": "iExec RLC", + "symbol": "RLC", + "decimals": 9, + "logoUrl": "https://assets.coingecko.com/coins/images/646/thumb/pL1VuXm.png?1604543202", + "priceUsd": null + }, + { + "chainId": 42161, + "address": "0xC8a4EeA31E9B6b61c406DF013DD4FEc76f21E279", + "name": "Render Token", + "symbol": "RNDR", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11636/thumb/rndr.png?1638840934", + "priceUsd": "2.19974286456683" + }, + { + "chainId": 42161, + "address": "0xB766039cc6DB368759C1E56B79AFfE831d0Cc507", + "name": "Rocket Pool Protocol", + "symbol": "RPL", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/2090/large/rocket_pool_%28RPL%29.png?1696503058", + "priceUsd": "13.352404593115276" + }, + { + "chainId": 42161, + "address": "0xCa5Ca9083702c56b481D1eec86F1776FDbd2e594", + "name": "Reserve Rights", + "symbol": "RSR", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/8365/large/RSR_Blue_Circle_1000.png?1721777856", + "priceUsd": "0.005257097361841642" + }, + { + "chainId": 42161, + "address": "0xd1318eb19DBF2647743c720ed35174efd64e3DAC", + "name": "The Sandbox", + "symbol": "SAND", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12129/thumb/sandbox_logo.jpg?1597397942", + "priceUsd": "0.20234260960480022" + }, + { + "chainId": 42161, + "address": "0x1629c4112952a7a377cB9B8d7d8c903092f34B63", + "name": "Stader", + "symbol": "SD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/20658/standard/SD_Token_Logo.png", + "priceUsd": "0.4256973462600656" + }, + { + "chainId": 42161, + "address": "0x5033833c9fe8B9d3E09EEd2f73d2aaF7E3872fd1", + "name": "Shiba Inu", + "symbol": "SHIB", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11939/thumb/shiba.png?1622619446", + "priceUsd": null + }, + { + "chainId": 42161, + "address": "0x4F9b7DEDD8865871dF65c5D26B1c2dD537267878", + "name": "SKALE", + "symbol": "SKL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/13245/thumb/SKALE_token_300x300.png?1606789574", + "priceUsd": "0.01836" + }, + { + "chainId": 42161, + "address": "0x707F635951193dDaFBB40971a0fCAAb8A6415160", + "name": "Status", + "symbol": "SNT", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/779/thumb/status.png?1548610778", + "priceUsd": "0.029259716991547478" + }, + { + "chainId": 42161, + "address": "0xcBA56Cd8216FCBBF3fA6DF6137F3147cBcA37D60", + "name": "Synthetix Network Token", + "symbol": "SNX", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png", + "priceUsd": "1.5577713343827964" + }, + { + "chainId": 42161, + "address": "0xb2BE52744a804Cc732d606817C2572C5A3B264e7", + "name": "Unisocks", + "symbol": "SOCKS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/10717/thumb/qFrcoiM.png?1582525244", + "priceUsd": "112814.27803552258" + }, + { + "chainId": 42161, + "address": "0xb74Da9FE2F96B9E0a5f4A3cf0b92dd2bEC617124", + "name": "SOL Wormhole ", + "symbol": "SOL", + "decimals": 9, + "logoUrl": "https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316", + "priceUsd": "187.66096555200232" + }, + { + "chainId": 42161, + "address": "0x3E6648C5a70A150A88bCE65F4aD4d506Fe15d2AF", + "name": "Spell Token", + "symbol": "SPELL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/15861/thumb/abracadabra-3.png?1622544862", + "priceUsd": "0.0003148202653241062" + }, + { + "chainId": 42161, + "address": "0x53e70cc1d527b524A1C46Eaa892e4CB35d2ba901", + "name": "SPX6900", + "symbol": "SPX", + "decimals": 8, + "logoUrl": "https://coin-images.coingecko.com/coins/images/31401/large/sticker_(1).jpg?1702371083", + "priceUsd": "0.899429863421002" + }, + { + "chainId": 42161, + "address": "0x1337420dED5ADb9980CFc35f8f2B054ea86f8aB1", + "name": "SQD", + "symbol": "SQD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/37869/standard/New_Logo_SQD_Icon.png?1720048443", + "priceUsd": null + }, + { + "chainId": 42161, + "address": "0xe018C7a3d175Fb0fE15D70Da2c874d3CA16313EC", + "name": "Stargate Finance", + "symbol": "STG", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24413/thumb/STG_LOGO.png?1647654518", + "priceUsd": "0.1386" + }, + { + "chainId": 42161, + "address": "0xE6320ebF209971b4F4696F7f0954b8457Aa2FCC2", + "name": "Storj Token", + "symbol": "STORJ", + "decimals": 8, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC/logo.png", + "priceUsd": "1.4221361441532103" + }, + { + "chainId": 42161, + "address": "0x7f9cf5a2630a0d58567122217dF7609c26498956", + "name": "SuperFarm", + "symbol": "SUPER", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14040/thumb/6YPdWn6.png?1613975899", + "priceUsd": "0.3652807599851772" + }, + { + "chainId": 42161, + "address": "0xA970AF1a584579B618be4d69aD6F73459D112F95", + "name": "Synth sUSD", + "symbol": "sUSD", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/5013/thumb/sUSD.png?1616150765", + "priceUsd": "0.983903" + }, + { + "chainId": 42161, + "address": "0xd4d42F0b6DEF4CE0383636770eF773390d85c61A", + "name": "Sushi", + "symbol": "SUSHI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688", + "priceUsd": "0.496788175409896" + }, + { + "chainId": 42161, + "address": "0x2C96bE2612bec20fe2975C3ACFcbBe61a58f2571", + "name": "Swell", + "symbol": "SWELL", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/28777/large/swell1.png?1727899715", + "priceUsd": "0.044145504444935216" + }, + { + "chainId": 42161, + "address": "0x1bCfc0B4eE1471674cd6A9F6B363A034375eAD84", + "name": "Synapse", + "symbol": "SYN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/18024/thumb/syn.png?1635002049", + "priceUsd": "0.07646961217875807" + }, + { + "chainId": 42161, + "address": "0x0945Cae3ae47cb384b2d47BC448Dc6A9dEC21F55", + "name": "Threshold Network", + "symbol": "T", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/22228/thumb/nFPNiSbL_400x400.jpg?1641220340", + "priceUsd": "0.01133572347593563" + }, + { + "chainId": 42161, + "address": "0x7E2a1eDeE171C5B19E6c54D73752396C0A572594", + "name": "tBTC", + "symbol": "tBTC", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/uniswap/assets/master/blockchains/ethereum/assets/0x18084fbA666a33d37592fA2633fD49a74DD93a88/logo.png", + "priceUsd": "57998.607571513734" + }, + { + "chainId": 42161, + "address": "0xd58D345Fd9c82262E087d2D0607624B410D88242", + "name": "Tellor", + "symbol": "TRB", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/9644/thumb/Blk_icon_current.png?1584980686", + "priceUsd": "25.24" + }, + { + "chainId": 42161, + "address": "0xBfAE6fecD8124ba33cbB2180aAb0Fe4c03914A5A", + "name": "Tribe", + "symbol": "TRIBE", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/14575/thumb/tribe.PNG?1617487954", + "priceUsd": "0.5698807253276615" + }, + { + "chainId": 42161, + "address": "0x5C816d4582c857dcadb1bB1F62Ad6c9DEde4576a", + "name": "Turbo", + "symbol": "TURBO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/30117/large/TurboMark-QL_200.png?1708079597", + "priceUsd": "0.010584978095424162" + }, + { + "chainId": 42161, + "address": "0xd693Ec944A85eeca4247eC1c3b130DCa9B0C3b22", + "name": "UMA Voting Token v1", + "symbol": "UMA", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828/logo.png", + "priceUsd": "4.746473582686635" + }, + { + "chainId": 42161, + "address": "0xFa7F8980b0f1E64A2062791cc3b0871572f1F7f0", + "name": "Uniswap", + "symbol": "UNI", + "decimals": 18, + "logoUrl": "ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg", + "priceUsd": "5.75" + }, + { + "chainId": 42161, + "address": "0x7550dE0A4b9Fb8CAbA8c32E72Ee356AFdd217A33", + "name": "World Liberty Financial USD", + "symbol": "USD1", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/54977/large/USD1_1000x1000_transparent.png?1749297002", + "priceUsd": "0.9352823300962718" + }, + { + "chainId": 42161, + "address": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", + "name": "USDCoin", + "symbol": "USDC", + "decimals": 6, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png", + "priceUsd": "0.999803" + }, + { + "chainId": 42161, + "address": "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", + "name": "Bridged USDC", + "symbol": "USDC.e", + "decimals": 6, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png", + "priceUsd": "0.999971" + }, + { + "chainId": 42161, + "address": "0x78df3a6044Ce3cB1905500345B967788b699dF8f", + "name": "Pax Dollar", + "symbol": "USDP", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/6013/standard/Pax_Dollar.png?1696506427", + "priceUsd": "1.003482886075035" + }, + { + "chainId": 42161, + "address": "0x6491c05A82219b8D1479057361ff1654749b876b", + "name": "USDS Stablecoin", + "symbol": "USDS", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/39926/large/usds.webp?1726666683", + "priceUsd": "0.999668" + }, + { + "chainId": 42161, + "address": "0x7639AB8599f1b417CbE4ceD492fB30162140AbbB", + "name": "USUAL", + "symbol": "USUAL", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/51091/large/USUAL.jpg?1730035787", + "priceUsd": "0.029257843871237324" + }, + { + "chainId": 42161, + "address": "0x1c8Ec4DE3c2BFD3050695D89853EC6d78AE650bb", + "name": "Wrapped Ampleforth", + "symbol": "WAMPL", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/20825/thumb/photo_2021-11-25_02-05-11.jpg?1637811951", + "priceUsd": "7.0704091793036" + }, + { + "chainId": 42161, + "address": "0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f", + "name": "Wrapped BTC", + "symbol": "WBTC", + "decimals": 8, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png", + "priceUsd": "109463" + }, + { + "chainId": 42161, + "address": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", + "name": "Wrapped Ether", + "symbol": "WETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3847.11" + }, + { + "chainId": 42161, + "address": "0x4D1d7134B87490AE5eEbdB22A5820d7d0E1980bf", + "name": "World Liberty Financial", + "symbol": "WLFI", + "decimals": 18, + "logoUrl": "https://coin-images.coingecko.com/coins/images/50767/large/wlfi.png?1756438915", + "priceUsd": "0.16894306684751884" + }, + { + "chainId": 42161, + "address": "0xcAFcD85D8ca7Ad1e1C6F82F651fA15E33AEfD07b", + "name": "WOO Network", + "symbol": "WOO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/12921/thumb/w2UiemF__400x400.jpg?1603670367", + "priceUsd": "0.0371699" + }, + { + "chainId": 42161, + "address": "0x58BbC087e36Db40a84b22c1B93a042294deEAFEd", + "name": "Chain", + "symbol": "XCN", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/24210/thumb/Chain_icon_200x200.png?1646895054", + "priceUsd": "0.008327717225644413" + }, + { + "chainId": 42161, + "address": "0xa05245Ade25cC1063EE50Cf7c083B4524c1C4302", + "name": "XSGD", + "symbol": "XSGD", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/12832/standard/StraitsX_Singapore_Dollar_%28XSGD%29_Token_Logo.png?1696512623", + "priceUsd": "0.7505057192568746" + }, + { + "chainId": 42161, + "address": "0x82e3A8F066a6989666b031d916c43672085b1582", + "name": "yearn finance", + "symbol": "YFI", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330", + "priceUsd": "2076.2856483704745" + }, + { + "chainId": 42161, + "address": "0x6DdBbcE7858D276678FC2B36123fD60547b88954", + "name": "Zetachain", + "symbol": "Zeta", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/26718/standard/Twitter_icon.png?1696525788", + "priceUsd": "0.1139" + }, + { + "chainId": 42161, + "address": "0x6985884C4392D348587B19cb9eAAf157F13271cd", + "name": "LayerZero", + "symbol": "ZRO", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208", + "priceUsd": "1.54" + }, + { + "chainId": 42161, + "address": "0xBD591Bd4DdB64b77B5f76Eab8f03d02519235Ae2", + "name": "0x Protocol Token", + "symbol": "ZRX", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png", + "priceUsd": "0.18603005525472147" + }, + { + "chainId": 81457, + "address": "0xb1a5700fA2358173Fe465e6eA4Ff52E36e88E2ad", + "name": "Blast", + "symbol": "BLAST", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/35494/standard/Blast.jpg?1719385662", + "priceUsd": "0.001320086757089162" + }, + { + "chainId": 7777777, + "address": "0xCccCCccc7021b32EBb4e8C08314bD62F7c653EC4", + "name": "USD Coin (Bridged from Ethereum)", + "symbol": "USDzC", + "decimals": 6, + "logoUrl": "https://assets.coingecko.com/coins/images/35218/large/USDC_Icon.png?1707908537", + "priceUsd": null + }, + { + "chainId": 1, + "address": "0x0000000000000000000000000000000000000000", + "name": "ETH", + "symbol": "ETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3847.11" + }, + { + "chainId": 10, + "address": "0x0000000000000000000000000000000000000000", + "name": "ETH", + "symbol": "ETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3847.11" + }, + { + "chainId": 137, + "address": "0x0000000000000000000000000000000000000000", + "name": "Polygon Ecosystem Token", + "symbol": "POL", + "decimals": 18, + "logoUrl": "https://static.debank.com/image/matic_token/logo_url/matic/6f5a6b6f0732a7a235131bd7804d357c.png", + "priceUsd": "0.196342" + }, + { + "chainId": 42161, + "address": "0x0000000000000000000000000000000000000000", + "name": "ETH", + "symbol": "ETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3847.11" + }, + { + "chainId": 324, + "address": "0x0000000000000000000000000000000000000000", + "name": "ETH", + "symbol": "ETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3854.97" + }, + { + "chainId": 8453, + "address": "0x0000000000000000000000000000000000000000", + "name": "ETH", + "symbol": "ETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3847.11" + }, + { + "chainId": 59144, + "address": "0x0000000000000000000000000000000000000000", + "name": "ETH", + "symbol": "ETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3854.88" + }, + { + "chainId": 34443, + "address": "0x0000000000000000000000000000000000000000", + "name": "ETH", + "symbol": "ETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3855.96" + }, + { + "chainId": 81457, + "address": "0x0000000000000000000000000000000000000000", + "name": "ETH", + "symbol": "ETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3854.88" + }, + { + "chainId": 1135, + "address": "0x0000000000000000000000000000000000000000", + "name": "ETH", + "symbol": "ETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3847.21" + }, + { + "chainId": 534352, + "address": "0x0000000000000000000000000000000000000000", + "name": "ETH", + "symbol": "ETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3852.4" + }, + { + "chainId": 480, + "address": "0x0000000000000000000000000000000000000000", + "name": "ETH", + "symbol": "ETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3852.4" + }, + { + "chainId": 57073, + "address": "0x0000000000000000000000000000000000000000", + "name": "ETH", + "symbol": "ETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3851.68" + }, + { + "chainId": 1868, + "address": "0x0000000000000000000000000000000000000000", + "name": "ETH", + "symbol": "ETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3843" + }, + { + "chainId": 130, + "address": "0x0000000000000000000000000000000000000000", + "name": "ETH", + "symbol": "ETH", + "decimals": 18, + "logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", + "priceUsd": "3847.11" + }, + { + "chainId": 232, + "address": "0x0000000000000000000000000000000000000000", + "name": "GHO", + "symbol": "GHO", + "decimals": 18, + "logoUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/23508.png", + "priceUsd": "0.999117" + }, + { + "chainId": 56, + "address": "0x0000000000000000000000000000000000000000", + "name": "BNB", + "symbol": "BNB", + "decimals": 18, + "logoUrl": "https://assets.coingecko.com/coins/images/825/small/binance-coin-logo.png?1547034615", + "priceUsd": "1080.71" + }, + { + "chainId": 999, + "address": "0x0000000000000000000000000000000000000000", + "name": "HYPE", + "symbol": "HYPE", + "decimals": 18, + "logoUrl": "https://static.debank.com/image/hyper_token/logo_url/hyper/0b3e288cfe418e9ce69eef4c96374583.png", + "priceUsd": "43.9" + }, + { + "chainId": 9745, + "address": "0x0000000000000000000000000000000000000000", + "name": "Plasma", + "symbol": "XPL", + "decimals": 18, + "logoUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/36645.png", + "priceUsd": "0.299542" + }, + { + "chainId": 34268394551451, + "address": "So11111111111111111111111111111111111111112", + "name": "Wrapped SOL", + "symbol": "SOL", + "decimals": 9, + "logoUrl": "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png", + "priceUsd": "186.3200331090853" + }, + { + "chainId": 34268394551451, + "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "name": "USD Coin", + "symbol": "USDC", + "decimals": 6, + "logoUrl": "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v/logo.png", + "priceUsd": "0.9997465009238741" + }, + { + "chainId": 34268394551451, + "address": "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB", + "name": "USDT", + "symbol": "USDT", + "decimals": 6, + "logoUrl": "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB/logo.svg", + "priceUsd": "0.9996110838259922" + }, + { + "chainId": 34268394551451, + "address": "9XgfFWPxPU6hyDyGtfhC9D6eyRE3RUSgAYKHRznWpump", + "name": "Remember KitKat", + "symbol": "kitkat", + "decimals": 6, + "logoUrl": "https://ipfs.io/ipfs/bafybeifzuhhw4jgzdkmydmdca4axo3can74baknh6snxtnarq74k5hcvwy", + "priceUsd": "0.004440595318926534" + }, + { + "chainId": 34268394551451, + "address": "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN", + "name": "Jupiter", + "symbol": "JUP", + "decimals": 6, + "logoUrl": "https://static.jup.ag/jup/icon.png", + "priceUsd": "0.40281147494070574" + }, + { + "chainId": 34268394551451, + "address": "DZpa4peCErsNzsYJ69XYYTSjZGDQhuexnzj7EiZ1pump", + "name": "KOMI", + "symbol": "KOMI", + "decimals": 6, + "logoUrl": "https://ipfs.io/ipfs/bafkreibrmbusvycbmdqbq66vwe3yhgxekepxvn72pgy2pzs7revch4lxxu", + "priceUsd": "0.0005294764153623442" + }, + { + "chainId": 34268394551451, + "address": "pumpCmXqMfrsAkQ5r49WcJnRayYRqmXz6ae8H7H9Dfn", + "name": "Pump", + "symbol": "PUMP", + "decimals": 6, + "logoUrl": "https://ipfs.io/ipfs/bafkreibyb3hcn7gglvdqpmklfev3fut3eqv3kje54l3to3xzxxbgpt5wjm", + "priceUsd": "0.004322366139506498" + }, + { + "chainId": 34268394551451, + "address": "J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn", + "name": "Jito Staked SOL", + "symbol": "JitoSOL", + "decimals": 9, + "logoUrl": "https://storage.googleapis.com/token-metadata/JitoSOL-256.png", + "priceUsd": "230.87032177657773" + }, + { + "chainId": 34268394551451, + "address": "Dz9mQ9NzkBcCsuGPFJ3r1bS4wgqKMHBPiVuniW8Mbonk", + "name": "USELESS COIN", + "symbol": "USELESS", + "decimals": 6, + "logoUrl": "https://i.imgur.com/S17YRd3.png", + "priceUsd": "0.23984569242225767" + }, + { + "chainId": 34268394551451, + "address": "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs", + "name": "Ether (Portal)", + "symbol": "ETH", + "decimals": 8, + "logoUrl": "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs/logo.png", + "priceUsd": "3840.0319677562097" + }, + { + "chainId": 34268394551451, + "address": "8fdBKZq7wo9fJbsZEZhq6omCgvKzLt97HY9XaGgqpump", + "name": "Neo 1x Companion", + "symbol": "NEO", + "decimals": 6, + "logoUrl": "https://metadata.rapidlaunch.io/images/4017f6bd-31db-4efd-815c-470d4464b193.png", + "priceUsd": "0.0026987590810477104" + }, + { + "chainId": 34268394551451, + "address": "BBKPiLM9KjdJW7oQSKt99RVWcZdhF6sEHRKnwqeBGHST", + "name": "GhostwareOS", + "symbol": "GHOST", + "decimals": 9, + "logoUrl": "https://gateway.irys.xyz/Ku6pbA57kzk-tyxlZP9NEOaA2SYAZtYl8bCSYTRlxjU", + "priceUsd": "0.018313766325202884" + }, + { + "chainId": 34268394551451, + "address": "E7NgL19JbN8BhUDgWjkH8MtnbhJoaGaWJqosxZZepump", + "name": "PayAI Network", + "symbol": "PAYAI", + "decimals": 6, + "logoUrl": "https://ipfs.io/ipfs/QmSd4swW6fkA3N92cUckYj1ar29mqpAaMzfwhrhgiFSonD", + "priceUsd": "0.03127903878201022" + }, + { + "chainId": 34268394551451, + "address": "9HAZrXJx5QXzBfJynRQXkHr9DG4Kk8dzuuQnMfz6pump", + "name": "XChange", + "symbol": "XCHANGE", + "decimals": 6, + "logoUrl": "https://ipfs.io/ipfs/bafkreidvgthhb6uc5eo7hxhj3gox27de4hm3mms4hbcxfclfwptqtoeoti", + "priceUsd": "0.0006915492091203927" + }, + { + "chainId": 34268394551451, + "address": "27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4", + "name": "Jupiter Perps", + "symbol": "JLP", + "decimals": 6, + "logoUrl": "https://static.jup.ag/jlp/icon.png", + "priceUsd": "5.4139616934890045" + }, + { + "chainId": 34268394551451, + "address": "6FrrzDk5mQARGc1TDYoyVnSyRdds1t4PbtohCD6p3tgG", + "name": "USX", + "symbol": "USX", + "decimals": 6, + "logoUrl": "https://raw.githubusercontent.com/Thomas-Solstice/usx-metadata/refs/heads/main/usx.png", + "priceUsd": "1.000431583630027" + }, + { + "chainId": 34268394551451, + "address": "63bpnCja1pGB2HSazkS8FAPAUkYgcXoDwYHfvZZveBot", + "name": "MasterBOT", + "symbol": "BOT", + "decimals": 6, + "logoUrl": "https://gateway.pinata.cloud/ipfs/QmWKBJJkPGyaELNDneg8ZNomuJyai3QG8c5DmoKVzkDxSR", + "priceUsd": "0.016849795830635655" + }, + { + "chainId": 34268394551451, + "address": "2zMMhcVQEXDtdE6vsFS7S7D5oUodfJHE8vd1gnBouauv", + "name": "Pudgy Penguins", + "symbol": "PENGU", + "decimals": 6, + "logoUrl": "https://arweave.net/BW67hICaKGd2_wamSB0IQq-x7Xwtmr2oJj1WnWGJRHU", + "priceUsd": "0.0184834844551566" + }, + { + "chainId": 34268394551451, + "address": "9BB6NFEcjBCtnNLFko2FqVQBq8HHM13kCyYcdQbgpump", + "name": "Fartcoin", + "symbol": "Fartcoin", + "decimals": 6, + "logoUrl": "https://ipfs.io/ipfs/QmQr3Fz4h1etNsF7oLGMRHiCzhB5y9a7GjyodnF7zLHK1g", + "priceUsd": "0.33378443731225843" + }, + { + "chainId": 34268394551451, + "address": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263", + "name": "Bonk", + "symbol": "Bonk", + "decimals": 5, + "logoUrl": "https://arweave.net/hQiPZOsRZXGXBJd_82PhVdlM_hACsT_q6wqwf5cSY7I", + "priceUsd": "0.000013616480029996904" + }, + { + "chainId": 34268394551451, + "address": "BANKJmvhT8tiJRsBSS1n2HryMBPvT5Ze4HU95DUAmeta", + "name": "Avici", + "symbol": "AVICI", + "decimals": 6, + "logoUrl": "https://raw.githubusercontent.com/metaDAOproject/futarchy/refs/heads/develop/scripts/assets/AVICI/AVICI.png", + "priceUsd": "2.345448625526105" + }, + { + "chainId": 34268394551451, + "address": "cbbtcf3aa214zXHbiAZQwf4122FBYbraNdFqgw4iMij", + "name": "Coinbase Wrapped BTC", + "symbol": "cbBTC", + "decimals": 8, + "logoUrl": "https://ipfs.io/ipfs/QmZ7L8yd5j36oXXydUiYFiFsRHbi3EdgC4RuFwvM7dcqge", + "priceUsd": "109548.97241997818" + }, + { + "chainId": 34268394551451, + "address": "METvsvVRapdj9cFLzq4Tr43xK4tAjQfwX76z3n6mWQL", + "name": "Meteora", + "symbol": "MET", + "decimals": 6, + "logoUrl": "https://assets.meteora.ag/met-token.svg", + "priceUsd": "0.45373699993445965" + }, + { + "chainId": 34268394551451, + "address": "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh", + "name": "Wrapped BTC (Portal)", + "symbol": "WBTC", + "decimals": 8, + "logoUrl": "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh/logo.png", + "priceUsd": "109771.8936206334" + }, + { + "chainId": 34268394551451, + "address": "3wPQhXYqy861Nhoc4bahtpf7G3e89XCLfZ67ptEfZUSA", + "name": "VALOR", + "symbol": "VALOR", + "decimals": 6, + "logoUrl": "https://ipfs.io/ipfs/QmX51VrS8HdyFYgwi33RrDCB894Zn4iWsikaBwu7x3WWyu", + "priceUsd": "0.012165380581697076" + }, + { + "chainId": 34268394551451, + "address": "5UUH9RTDiSpq6HKS6bp4NdU9PNJpXRXuiw6ShBTBhgH2", + "name": "TROLL", + "symbol": "TROLL", + "decimals": 6, + "logoUrl": "https://ipfs.io/ipfs/QmWV8QgmH1gSw41yapzsFwkC8yPbzoSreAcJbzqfvo2sVq", + "priceUsd": "0.08042749053521396" + }, + { + "chainId": 34268394551451, + "address": "J3NKxxXZcnNiMjKw9hYb2K4LUxgwB6t1FtPtQVsv3KFr", + "name": "SPX6900 (Wormhole)", + "symbol": "SPX", + "decimals": 8, + "logoUrl": "https://i.imgur.com/fLpAyY4.png", + "priceUsd": "0.8926403677495987" + }, + { + "chainId": 34268394551451, + "address": "USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB", + "name": "World Liberty Financial USD", + "symbol": "USD1", + "decimals": 6, + "logoUrl": "https://raw.githubusercontent.com/worldliberty/usd1-metadata/refs/heads/main/logo.png", + "priceUsd": "0.9991369459533918" + }, + { + "chainId": 34268394551451, + "address": "Ey59PH7Z4BFU4HjyKnyMdWt5GGN76KazTAwQihoUXRnk", + "name": "Launch Coin on Believe", + "symbol": "LAUNCHCOIN", + "decimals": 9, + "logoUrl": "https://ipfs.io/ipfs/bafkreibeqt7fvgn2ubl4tha6sljnici2eus42dauxgtrdvfjf6m3vkdkoi", + "priceUsd": "0.00038137088275708067" + }, + { + "chainId": 34268394551451, + "address": "9BEcn9aPEmhSPbPQeFGjidRiEKki46fVQDyPpSQXPA2D", + "name": "jupiter lend USDC", + "symbol": "jlUSDC", + "decimals": 6, + "logoUrl": "https://cdn.instadapp.io/solana/tokens/icons/usdc.png", + "priceUsd": "1.017138460368136" + }, + { + "chainId": 34268394551451, + "address": "oreoU2P8bN6jkk3jbaiVxYnG1dCXcYxwhwyK9jSybcp", + "name": "ORE", + "symbol": "ORE", + "decimals": 11, + "logoUrl": "https://ore.supply/assets/icon.png", + "priceUsd": "151.32430778176268" + }, + { + "chainId": 34268394551451, + "address": "BFgdzMkTPdKKJeTipv2njtDEwhKxkgFueJQfJGt1jups", + "name": "Uranus", + "symbol": "URANUS", + "decimals": 6, + "logoUrl": "https://static-create.jup.ag/images/BFgdzMkTPdKKJeTipv2njtDEwhKxkgFueJQfJGt1jups-8c6c089e-20b9-4114-9dc3-e77103318edf.jpg", + "priceUsd": "0.4456947517369835" + }, + { + "chainId": 34268394551451, + "address": "BLVxek8YMXUQhcKmMvrFTrzh5FXg8ec88Crp6otEaCMf", + "name": "Believe", + "symbol": "BELIEVE", + "decimals": 9, + "logoUrl": "https://ipfs.io/ipfs/bafkreiadp3asuncuej2pzmvbrmzs2slrxyqbb6wpht4bizjixoz4uijiyu", + "priceUsd": "0.03861308877714471" + }, + { + "chainId": 34268394551451, + "address": "GEuuznWpn6iuQAJxLKQDVGXPtrqXHNWTk3gZqqvJpump", + "name": "Ace Data Cloud", + "symbol": "ACE", + "decimals": 6, + "logoUrl": "https://ipfs.io/ipfs/QmSSu7Mgyo4Ua8Gb6jAMwyMFE97aM8gZhAUH5wZ2ZS7nfS", + "priceUsd": "0.008934811599365813" + }, + { + "chainId": 34268394551451, + "address": "BULKoNSGzxtCqzwTvg5hFJg8fx6dqZRScyXe5LYMfxrn", + "name": "BULK Staked SOL", + "symbol": "BulkSOL", + "decimals": 9, + "logoUrl": "https://arweave.net/tBlyAYsdhdXFdAUO7OeEZdcZ-KYXYgR8DAEPjx7akig", + "priceUsd": "195.7036945248328" + }, + { + "chainId": 34268394551451, + "address": "6p6xgHyF7AeE6TZkSmFsko444wqoP15icUSqi2jfGiPN", + "name": "OFFICIAL TRUMP", + "symbol": "TRUMP", + "decimals": 6, + "logoUrl": "https://arweave.net/VQrPjACwnQRmxdKBTqNwPiyo65x7LAT773t8Kd7YBzw", + "priceUsd": "7.956380985453473" + }, + { + "chainId": 34268394551451, + "address": "HeLp6NuQkmYB4pYWo2zYs22mESHXPQYzXbB8n4V98jwC", + "name": "ai16z", + "symbol": "ai16z", + "decimals": 9, + "logoUrl": "https://ipfs.io/ipfs/QmcNTVAoyJ7zDbPnN9jwiMoB8uCoJBUP9RGmmiGGHv44yX", + "priceUsd": "0.08356594602103513" + }, + { + "chainId": 1337, + "address": "0x200000000000000000000000000000000000010C", + "name": "Tether USD", + "symbol": "USDT-SPOT", + "decimals": 8, + "logoUrl": "https://raw.githubusercontent.com/across-protocol/frontend/master/src/assets/token-logos/usdt-spot.svg", + "priceUsd": "1" + } + ], + "timestamp": 1761918182873, + "version": "1.0.0" +} diff --git a/src/hooks/index.ts b/src/hooks/index.ts index ae9e47b5d..2933bf102 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -17,3 +17,4 @@ export * from "./useWalletTrace"; export * from "./useQueue"; export * from "./useAmplitude"; export * from "./useRewardSummary"; +export * from "./useTokenInput"; diff --git a/src/hooks/useAvailableCrosschainRoutes.ts b/src/hooks/useAvailableCrosschainRoutes.ts new file mode 100644 index 000000000..70dbcc6ce --- /dev/null +++ b/src/hooks/useAvailableCrosschainRoutes.ts @@ -0,0 +1,74 @@ +import { useQuery } from "@tanstack/react-query"; +import { useSwapTokens } from "./useSwapTokens"; + +export type LifiToken = { + chainId: number; + address: string; + symbol: string; + name: string; + decimals: number; + priceUSD: string; + coinKey: string; + logoURI: string; + routeSource: "bridge" | "swap"; +}; + +export type TokenInfo = { + chainId: number; + address: string; + symbol: string; +}; + +export type RouteFilterParams = { + inputToken?: TokenInfo | null; + outputToken?: TokenInfo | null; +}; + +export default function useAvailableCrosschainRoutes( + filterParams?: RouteFilterParams +) { + const swapTokensQuery = useSwapTokens(); + + return useQuery({ + queryKey: ["availableCrosschainRoutes", filterParams], + queryFn: async () => { + // Build token map by chain from API tokens + const tokensByChain = (swapTokensQuery.data || []).reduce( + (acc, token) => { + // Get the chainId from the addresses record (TokenInfo has addresses object) + const chainIds = token.addresses + ? Object.keys(token.addresses).map(Number) + : []; + + chainIds.forEach((chainId) => { + const address = token.addresses?.[chainId]; + if (!address) return; + + const mapped: LifiToken = { + chainId: chainId, + address: address, + name: token.name, + symbol: token.symbol, + decimals: token.decimals, + logoURI: token.logoURI || "", + priceUSD: token.priceUsd || "0", // Use price from SwapToken, fallback to "0" if not available + coinKey: token.symbol, + routeSource: "swap", + }; + + if (!acc[chainId]) { + acc[chainId] = []; + } + acc[chainId].push(mapped); + }); + + return acc; + }, + {} as Record> + ); + + return tokensByChain; + }, + enabled: swapTokensQuery.isSuccess, + }); +} diff --git a/src/hooks/useConnectionSVM.ts b/src/hooks/useConnectionSVM.ts index 38309b0ba..fa13417e7 100644 --- a/src/hooks/useConnectionSVM.ts +++ b/src/hooks/useConnectionSVM.ts @@ -73,7 +73,11 @@ export function useConnectionSVM() { ); return { - chainId: hubPoolChainId === 1 ? solana.chainId : solanaDevnet.chainId, + chainId: !connected + ? 0 + : hubPoolChainId === 1 + ? solana.chainId + : solanaDevnet.chainId, account: publicKey, select, state, diff --git a/src/hooks/useEnrichedCrosschainBalances.ts b/src/hooks/useEnrichedCrosschainBalances.ts new file mode 100644 index 000000000..6d4a9924b --- /dev/null +++ b/src/hooks/useEnrichedCrosschainBalances.ts @@ -0,0 +1,68 @@ +import { useMemo } from "react"; +import useAvailableCrosschainRoutes, { + LifiToken, +} from "./useAvailableCrosschainRoutes"; +import { useUserTokenBalances } from "./useUserTokenBalances"; +import { compareAddressesSimple } from "utils"; +import { BigNumber, utils } from "ethers"; + +export function useEnrichedCrosschainBalances() { + const tokenBalances = useUserTokenBalances(); + const availableCrosschainRoutes = useAvailableCrosschainRoutes(); + + return useMemo(() => { + if (availableCrosschainRoutes.isLoading || tokenBalances.isLoading) { + return {}; + } + const chains = Object.keys(availableCrosschainRoutes.data || {}); + + return chains.reduce( + (acc, chainId) => { + const balancesForChain = tokenBalances.data?.balances.find( + (t) => t.chainId === String(chainId) + ); + + const tokens = availableCrosschainRoutes.data![Number(chainId)]; + const enrichedTokens = tokens.map((t) => { + const balance = balancesForChain?.balances.find((b) => + compareAddressesSimple(b.address, t.address) + ); + return { + ...t, + balance: balance?.balance + ? BigNumber.from(balance.balance) + : BigNumber.from(0), + balanceUsd: + balance?.balance && t + ? Number( + utils.formatUnits( + BigNumber.from(balance.balance), + t.decimals + ) + ) * Number(t.priceUSD) + : 0, + }; + }); + + // Sort high to low balanceUsd + const sortedByBalance = enrichedTokens.sort( + (a, b) => b.balanceUsd - a.balanceUsd + ); + + return { + ...acc, + [Number(chainId)]: sortedByBalance, + }; + }, + {} as Record< + number, + Array + > + ); + }, [ + availableCrosschainRoutes.data, + availableCrosschainRoutes.isLoading, + tokenBalances.data, + tokenBalances.isLoading, + ]); +} diff --git a/src/hooks/useSwapChains.ts b/src/hooks/useSwapChains.ts new file mode 100644 index 000000000..96356deb0 --- /dev/null +++ b/src/hooks/useSwapChains.ts @@ -0,0 +1,12 @@ +import { useQuery } from "@tanstack/react-query"; +import getApiEndpoint from "utils/serverless-api"; + +export function useSwapChains() { + return useQuery({ + queryKey: ["swapChains"], + queryFn: async () => { + const api = getApiEndpoint(); + return await api.swapChains(); + }, + }); +} diff --git a/src/hooks/useSwapQuote.ts b/src/hooks/useSwapQuote.ts index 63e5e0464..03490b2dc 100644 --- a/src/hooks/useSwapQuote.ts +++ b/src/hooks/useSwapQuote.ts @@ -63,7 +63,8 @@ export function useSwapQuoteQuery(params: SwapQuoteQueryKeyParams) { }); }, enabled: !!params.swapTokenSymbol, - refetchInterval: 5_000, + retry: 3, + refetchInterval: 10_000, }); } diff --git a/src/hooks/useSwapTokens.ts b/src/hooks/useSwapTokens.ts new file mode 100644 index 000000000..d79a894a0 --- /dev/null +++ b/src/hooks/useSwapTokens.ts @@ -0,0 +1,57 @@ +import { useQuery } from "@tanstack/react-query"; +import getApiEndpoint from "utils/serverless-api"; +import { swapTokenToTokenInfo } from "utils/token"; +import { TokenInfo } from "constants/tokens"; + +// Import cached tokens data +import cachedTokensData from "../data/swap-tokens.json"; +import { SwapToken } from "utils/serverless-api/types"; +import { SwapTokensQuery } from "utils/serverless-api/prod/swap-tokens"; + +type SwapTokensCache = { + tokens: SwapToken[]; + timestamp: number; + version: string; +}; + +function filterTokensByChainId( + tokens: SwapToken[], + chainId?: number | number[] +): SwapToken[] { + if (!chainId) { + return tokens; + } + + const chainIds = Array.isArray(chainId) ? chainId : [chainId]; + return tokens.filter((token) => chainIds.includes(token.chainId)); +} + +function convertSwapTokensToTokenInfo(tokens: SwapToken[]): TokenInfo[] { + return tokens.map((token) => swapTokenToTokenInfo(token)); +} + +export function useSwapTokens(query?: SwapTokensQuery) { + return useQuery({ + queryKey: ["swapTokens", query], + queryFn: async () => { + const api = getApiEndpoint(); + const tokens = await api.swapTokens(query); + return convertSwapTokensToTokenInfo(tokens); + }, + // Use cached data as initial data for immediate loading + initialData: () => { + try { + const cache = cachedTokensData as SwapTokensCache; + const filteredTokens = filterTokensByChainId( + cache.tokens, + query?.chainId + ); + return convertSwapTokensToTokenInfo(filteredTokens); + } catch (error) { + console.warn("Failed to load cached swap tokens:", error); + return undefined; + } + }, + refetchInterval: 60_000, + }); +} diff --git a/src/hooks/useTabIndexManager.ts b/src/hooks/useTabIndexManager.ts new file mode 100644 index 000000000..1d898af30 --- /dev/null +++ b/src/hooks/useTabIndexManager.ts @@ -0,0 +1,54 @@ +import { useEffect, useRef } from "react"; + +/** + * Custom hook that manages tab indices for modal content + * When active, it sets all elements outside the modal to tabindex="-1" + * and restores their original tabindex values when inactive + * @param isActive - Whether the tab index management should be active + * @param containerRef - Reference to the container element to preserve tab indices within + */ +export const useTabIndexManager = ( + isActive: boolean, + containerRef: React.RefObject +) => { + const originalTabIndices = useRef>(new Map()); + + useEffect(() => { + if (!isActive || !containerRef.current) { + return; + } + + const modalElement = containerRef.current; + const tabIndicesMap = originalTabIndices.current; + + // Only target elements that are naturally focusable + const focusableElements = document.querySelectorAll( + "button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), a[href], [tabindex]:not([tabindex='-1'])" + ) as NodeListOf; + + // Store original tabindex values and set elements outside modal to tabindex="-1" + focusableElements.forEach((element) => { + // Skip elements inside the modal + if (modalElement.contains(element)) { + return; + } + + const currentTabIndex = element.getAttribute("tabindex"); + tabIndicesMap.set(element, currentTabIndex); + element.setAttribute("tabindex", "-1"); + }); + + // Cleanup function + return () => { + // Restore original tabindex values + tabIndicesMap.forEach((originalTabIndex, element) => { + if (originalTabIndex === null) { + element.removeAttribute("tabindex"); + } else { + element.setAttribute("tabindex", originalTabIndex); + } + }); + tabIndicesMap.clear(); + }; + }, [isActive, containerRef]); +}; diff --git a/src/hooks/useToken.ts b/src/hooks/useToken.ts new file mode 100644 index 000000000..c1ba79522 --- /dev/null +++ b/src/hooks/useToken.ts @@ -0,0 +1,80 @@ +import { useMemo } from "react"; +import { + getToken, + TOKEN_SYMBOLS_MAP, + TokenInfo, + applyChainSpecificTokenDisplay, +} from "utils"; +import { orderedTokenLogos } from "../constants/tokens"; +import { useSwapTokens } from "./useSwapTokens"; +import unknownLogo from "assets/icons/question-circle.svg"; + +/** + * Hook to resolve token info for a given symbol + * Resolution order: + * 1. Try getToken from constants + * 2. Try TOKEN_SYMBOLS_MAP directly (local definitions) + * 3. Fallback to swap tokens from API + * + * If chainId is provided, applies chain-specific display modifications (e.g., USDT -> USDT0) + */ +export function useToken( + symbol: string, + chainId?: number +): TokenInfo | undefined { + const { data: swapTokens } = useSwapTokens(); + + const token = useMemo(() => { + let resolvedToken: TokenInfo | undefined; + + // Try to get token from constants first + try { + resolvedToken = getToken(symbol); + } catch (error) { + // If getToken fails, try TOKEN_SYMBOLS_MAP directly + const tokenFromMap = + TOKEN_SYMBOLS_MAP[ + symbol.toUpperCase() as keyof typeof TOKEN_SYMBOLS_MAP + ]; + + if (tokenFromMap) { + // Get logoURI from orderedTokenLogos or use unknown logo + const logoURI = + orderedTokenLogos[ + symbol.toUpperCase() as keyof typeof orderedTokenLogos + ] || unknownLogo; + + resolvedToken = { + ...tokenFromMap, + logoURI, + } as TokenInfo; + } else if (swapTokens) { + // If still not found, try to find it in swap API data + // Search across all chains for a token with matching symbol + // Note: swapTokens is now already converted to TokenInfo[] + const foundToken = swapTokens.find( + (t) => t.symbol.toUpperCase() === symbol.toUpperCase() + ); + + if (foundToken) { + resolvedToken = foundToken; + } + } + + // If still not found, log warning + if (!resolvedToken) { + console.warn(`Unable to resolve token info for symbol ${symbol}`); + return undefined; + } + } + + // Apply chain-specific display modifications if chainId is provided + if (chainId !== undefined) { + return applyChainSpecificTokenDisplay(resolvedToken, chainId); + } + + return resolvedToken; + }, [symbol, chainId, swapTokens]); + + return token; +} diff --git a/src/hooks/useTokenConversion.ts b/src/hooks/useTokenConversion.ts index dc283c24b..5c93773a1 100644 --- a/src/hooks/useTokenConversion.ts +++ b/src/hooks/useTokenConversion.ts @@ -3,13 +3,13 @@ import { BigNumber, BigNumberish, ethers } from "ethers"; import { useCallback } from "react"; import { fixedPointAdjustment, - getToken, TOKEN_SYMBOLS_MAP, isDefined, getConfig, hubPoolChainId, } from "utils"; import { ConvertDecimals } from "utils/convertdecimals"; +import { useToken } from "./useToken"; const config = getConfig(); @@ -18,16 +18,17 @@ export function useTokenConversion( baseCurrency: string, historicalDateISO?: string ) { - const token = getToken(symbol); + // Use the useToken hook to resolve token info + const token = useToken(symbol); // If the token is OP, we need to use the address of the token on Optimism const l1Token = - token.symbol === "OP" + token?.symbol === "OP" ? TOKEN_SYMBOLS_MAP["OP"].addresses[10] - : token.mainnetAddress!; + : token?.mainnetAddress; const query = useCoingeckoPrice( - l1Token, + l1Token || "", baseCurrency, historicalDateISO, isDefined(l1Token) @@ -38,7 +39,9 @@ export function useTokenConversion( const price = query.data?.price; const decimals = token?.decimals ?? - config.getTokenInfoByAddressSafe(hubPoolChainId, l1Token)?.decimals; + (l1Token + ? config.getTokenInfoByAddressSafe(hubPoolChainId, l1Token)?.decimals + : undefined); if (!isDefined(price) || !isDefined(amount) || !isDefined(decimals)) { return undefined; @@ -55,7 +58,9 @@ export function useTokenConversion( const price = query.data?.price; const decimals = token?.decimals ?? - config.getTokenInfoByAddressSafe(hubPoolChainId, l1Token)?.decimals; + (l1Token + ? config.getTokenInfoByAddressSafe(hubPoolChainId, l1Token)?.decimals + : undefined); if (!isDefined(price) || !isDefined(amount) || !isDefined(decimals)) { return undefined; diff --git a/src/hooks/useTokenInput.ts b/src/hooks/useTokenInput.ts new file mode 100644 index 000000000..5e884417c --- /dev/null +++ b/src/hooks/useTokenInput.ts @@ -0,0 +1,216 @@ +import { useCallback, useEffect, useState } from "react"; +import { BigNumber, utils } from "ethers"; +import { convertTokenToUSD, convertUSDToToken } from "utils"; +import { EnrichedToken } from "views/SwapAndBridge/components/ChainTokenSelector/ChainTokenSelectorModal"; +import { formatUnitsWithMaxFractions } from "utils"; + +export type UnitType = "usd" | "token"; + +type UseTokenInputProps = { + token: EnrichedToken | null; + setAmount: (amount: BigNumber | null) => void; + expectedAmount: string | undefined; + shouldUpdate: boolean; + isUpdateLoading: boolean; + // Optional: Allow unit state to be controlled from parent + unit?: UnitType; + setUnit?: (unit: UnitType) => void; +}; + +type UseTokenInputReturn = { + amountString: string; + setAmountString: (value: string) => void; + unit: UnitType; + convertedAmount: BigNumber | undefined; + toggleUnit: () => void; + handleInputChange: (value: string) => void; + handleBalanceClick: (amount: BigNumber, decimals: number) => void; +}; + +export function useTokenInput({ + token, + setAmount, + expectedAmount, + shouldUpdate, + isUpdateLoading, + unit: externalUnit, + setUnit: externalSetUnit, +}: UseTokenInputProps): UseTokenInputReturn { + const [amountString, setAmountString] = useState(""); + const [internalUnit, setInternalUnit] = useState("token"); + const [convertedAmount, setConvertedAmount] = useState(); + const [justTyped, setJustTyped] = useState(false); + + // Use external unit if provided, otherwise use internal state + const unit = externalUnit ?? internalUnit; + const setUnit = externalSetUnit ?? setInternalUnit; + + // Handle user input changes - propagate to parent + useEffect(() => { + if (!justTyped) { + return; + } + setJustTyped(false); + try { + if (!token) { + setAmount(null); + return; + } + // If the input is empty or effectively zero, set amount to null + if (!amountString || !Number(amountString)) { + setAmount(null); + return; + } + if (unit === "token") { + const parsed = utils.parseUnits(amountString, token.decimals); + // If parsed amount is zero or negative, set to null + if (parsed.lte(0)) { + setAmount(null); + return; + } + setAmount(parsed); + } else { + const tokenValue = convertUSDToToken(amountString, token); + // If converted value is zero or negative, set to null + if (tokenValue.lte(0)) { + setAmount(null); + return; + } + setAmount(tokenValue); + } + } catch (e) { + setAmount(null); + } + }, [amountString, justTyped, token, unit, setAmount]); + + // Reset amount when token changes + useEffect(() => { + if (token) { + setAmountString(""); + setConvertedAmount(undefined); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [token?.chainId, token?.symbol]); + + // Handle quote updates - only update the field that should receive the quote + useEffect(() => { + if (shouldUpdate && isUpdateLoading) { + setAmountString(""); + } + + if (shouldUpdate && token) { + // Clear the field when there's no expected amount and not loading + if (!expectedAmount && !isUpdateLoading) { + setAmountString(""); + } else { + if (expectedAmount) { + if (unit === "token") { + // Display as token amount + setAmountString( + formatUnitsWithMaxFractions(expectedAmount, token.decimals) + ); + } else { + // Display as USD amount - convert token to USD + const tokenAmountFormatted = formatUnitsWithMaxFractions( + expectedAmount, + token.decimals + ); + const usdValue = convertTokenToUSD(tokenAmountFormatted, token); + // convertTokenToUSD returns in 18 decimal precision + setAmountString(utils.formatUnits(usdValue, 18)); + } + } + } + } + }, [expectedAmount, isUpdateLoading, shouldUpdate, token, unit]); + + // Set converted value for display + useEffect(() => { + if (!token || !amountString) { + setConvertedAmount(undefined); + return; + } + try { + if (unit === "token") { + // User typed token amount - convert to USD for display + const usdValue = convertTokenToUSD(amountString, token); + setConvertedAmount(usdValue); + } else { + // User typed USD amount - convert to token for display + const tokenValue = convertUSDToToken(amountString, token); + setConvertedAmount(tokenValue); + } + } catch (e) { + // getting an underflow error here + setConvertedAmount(undefined); + } + }, [token, amountString, unit]); + + // Toggle between token and USD units + const toggleUnit = useCallback(() => { + if (unit === "token") { + // Convert token amount to USD string for display + if (amountString && token && convertedAmount) { + try { + // convertedAmount is USD value in 18 decimals + const a = utils.formatUnits(convertedAmount, 18); + setAmountString(a); + } catch (e) { + setAmountString("0"); + } + } + setUnit("usd"); + } else { + // Convert USD amount to token string for display + if (amountString && token && convertedAmount) { + try { + // convertedAmount is token value in token's native decimals + const a = utils.formatUnits(convertedAmount, token.decimals); + setAmountString(a); + } catch (e) { + setAmountString("0"); + } + } + setUnit("token"); + } + }, [unit, amountString, token, convertedAmount, setUnit]); + + // Handle input field changes + const handleInputChange = useCallback((value: string) => { + if (value === "" || /^\d*\.?\d*$/.test(value)) { + setJustTyped(true); + setAmountString(value); + } + }, []); + + // Handle balance selector click + const handleBalanceClick = useCallback( + (amount: BigNumber, decimals: number) => { + setAmount(amount); + if (unit === "usd" && token) { + // Convert token amount to USD for display + const tokenAmountFormatted = formatUnitsWithMaxFractions( + amount, + decimals + ); + const usdValue = convertTokenToUSD(tokenAmountFormatted, token); + // convertTokenToUSD returns in 18 decimal precision + setAmountString(utils.formatUnits(usdValue, 18)); + } else { + // Display as token amount + setAmountString(formatUnitsWithMaxFractions(amount, decimals)); + } + }, + [setAmount, unit, token] + ); + + return { + amountString, + setAmountString, + unit, + convertedAmount, + toggleUnit, + handleInputChange, + handleBalanceClick, + }; +} diff --git a/src/hooks/useUserTokenBalances.ts b/src/hooks/useUserTokenBalances.ts new file mode 100644 index 000000000..7195a93ad --- /dev/null +++ b/src/hooks/useUserTokenBalances.ts @@ -0,0 +1,54 @@ +import { useQuery } from "@tanstack/react-query"; +import { UserTokenBalancesResponse } from "utils/serverless-api/types"; +import getApiEndpoint from "utils/serverless-api"; +import { useConnectionEVM } from "./useConnectionEVM"; +import { useConnectionSVM } from "./useConnectionSVM"; + +export function useUserTokenBalances() { + const { account: evmAccount } = useConnectionEVM(); + const { account: svmAccount } = useConnectionSVM(); + + // Convert SVM PublicKey to string if it exists + const svmAccountString = svmAccount?.toString(); + + return useQuery({ + queryKey: makeUseUserTokenBalancesQueryKey([evmAccount, svmAccountString]), + queryFn: async (): Promise => { + // Fetch balances for both accounts if they exist + const promises: Promise[] = []; + + if (evmAccount) { + promises.push(getApiEndpoint().userTokenBalances(evmAccount)); + } + + if (svmAccountString) { + promises.push(getApiEndpoint().userTokenBalances(svmAccountString)); + } + + if (promises.length === 0) { + throw new Error("No account connected"); + } + + // Fetch all balances in parallel + const results = await Promise.all(promises); + + // Merge the results + if (results.length === 1) { + return results[0]; + } + + // Merge balances from both EVM and SVM accounts + return { + account: evmAccount || svmAccountString || "", + balances: results.flatMap((result) => result.balances), + }; + }, + enabled: !!evmAccount || !!svmAccountString, + refetchInterval: 5 * 60 * 1000, // Refetch every 5 minutes + staleTime: 3 * 60 * 1000, // Consider data stale after 3 minutes + }); +} + +export const makeUseUserTokenBalancesQueryKey = ( + keys?: Parameters[0]["queryKey"] +) => ["userTokenBalances", ...(keys ? keys : [])]; diff --git a/src/utils/amplitude.ts b/src/utils/amplitude.ts index 206fa5d55..5caf5c64c 100644 --- a/src/utils/amplitude.ts +++ b/src/utils/amplitude.ts @@ -70,8 +70,8 @@ export function getPageValue() { const path = getSanitizedPathname(); // Check if the path is a deposit status page. We know that the - // deposit status page will always have a path that starts with /bridge/0x{tx hash} - if (/\/bridge\/0x[0-9a-fA-F]+/.test(path)) { + // deposit status page will always have a path that starts with /bridge-and-swap/0x{tx hash} + if (/\/bridge-and-swap\/0x[0-9a-fA-F]+/.test(path)) { return "depositStatusPage"; } diff --git a/src/utils/colors.ts b/src/utils/colors.ts new file mode 100644 index 000000000..83bbf4d88 --- /dev/null +++ b/src/utils/colors.ts @@ -0,0 +1,13 @@ +/** + * Simple utility to change color opacity using color-mix + */ + +/** + * Creates a color with a specific opacity using color-mix + * @param color - The base color (any valid CSS color) + * @param opacity - The opacity value (0-1) + * @returns The color with the specified opacity + */ +export function withOpacity(color: string, opacity: number): string { + return `color-mix(in srgb, ${color} ${opacity * 100}%, transparent)`; +} diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 9f21d0030..4a0ac2bb4 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -1,10 +1,14 @@ import assert from "assert"; import { BigNumber, ethers, providers } from "ethers"; + import { CHAIN_IDs, PUBLIC_NETWORKS, TOKEN_SYMBOLS_MAP, } from "@across-protocol/constants"; + +export { CHAIN_IDs } from "@across-protocol/constants"; + import * as superstruct from "superstruct"; import { parseEtherLike } from "./format"; @@ -310,15 +314,17 @@ export const getToken = (symbol: string): TokenInfo => { }; /** - * Gets token info with chain-specific display modifications (temporary for USDT0) - * This is a temporary function that will be removed once all chains migrate to USDT0 + * Apply chain-specific display modifications to a token + * Currently handles: USDT -> USDT0 for supported chains + * + * @param token Token info to transform + * @param chainId Chain ID to apply transformations for + * @returns Transformed token info, or original if no transformations needed */ -export const getTokenForChain = ( - symbol: string, +export function applyChainSpecificTokenDisplay( + token: TokenInfo, chainId: number -): TokenInfo => { - const token = getToken(symbol); - +): TokenInfo { // Handle USDT -> USDT0 display for specific chains if (token.symbol === "USDT" && chainsWithUsdt0Enabled.includes(chainId)) { return { @@ -329,7 +335,7 @@ export const getTokenForChain = ( } return token; -}; +} export const getRewardToken = (deposit: Deposit): TokenInfo | undefined => { if (!deposit.rewards) { diff --git a/src/utils/errors.ts b/src/utils/errors.ts index 5e38607b7..2f2c9078d 100644 --- a/src/utils/errors.ts +++ b/src/utils/errors.ts @@ -1,3 +1,4 @@ +import axios, { AxiosError } from "axios"; import { ChainId } from "./constants"; export class UnsupportedChainIdError extends Error { @@ -58,3 +59,71 @@ export class InsufficientBalanceError extends Error { this.message = "Insufficient balance."; } } + +export type AcrossApiErrorResponse = { + code?: string; + message?: string; +}; + +export function getQuoteWarningMessage(error: Error | null): string | null { + if (!error || !axios.isAxiosError(error)) { + return null; + } + + const axiosError = error as AxiosError; + + const errorData = axiosError.response?.data; + if (!errorData?.code) { + return null; + } + + const code = errorData.code; + const message = errorData.message; + + // Upstream swap provider errors - show user-friendly messages + switch (code) { + case "SWAP_LIQUIDITY_INSUFFICIENT": + return "Insufficient liquidity available for this swap. Try a smaller amount or different tokens."; + + case "SWAP_QUOTE_UNAVAILABLE": + return message?.includes("No possible route") + ? "No route found for this token pair. Try selecting different tokens." + : "Unable to get a quote at this time. Please try again."; + + case "SWAP_TYPE_NOT_GUARANTEED": + return "This trade type cannot be guaranteed on this route. Try a different amount or token pair."; + + case "AMOUNT_TOO_LOW": + return "Amount is too low to cover bridge and swap fees. Try increasing the amount."; + + case "AMOUNT_TOO_HIGH": + return "Amount exceeds the maximum deposit limit. Try a smaller amount."; + + case "ROUTE_NOT_ENABLED": + return "This route is currently unavailable. Try different chains or tokens."; + + case "INVALID_PARAM": + // return "Invalid parameters. Please check your input and try again."; + if (!message) { + return "Unable to get a quote at this time. Please try again."; + } + if ( + message?.includes("doesn't have enough funds to support this deposit") + ) { + return "Amount too high. Try a smaller amount."; + } + return message; + + // Upstream service errors - be more generic + case "UPSTREAM_HTTP_ERROR": + case "UPSTREAM_RPC_ERROR": + case "UPSTREAM_GATEWAY_TIMEOUT": + case "UNEXPECTED_ERROR": + case "SIMULATION_ERROR": + case "ABI_ENCODING_ERROR": + case "INVALID_METHOD": + case "MISSING_PARAM": + default: + return "Oops, something went wrong. Please try again."; + } +} diff --git a/src/utils/format.ts b/src/utils/format.ts index 626a1d06a..76f98d9d0 100644 --- a/src/utils/format.ts +++ b/src/utils/format.ts @@ -295,11 +295,15 @@ export function humanReadableNumber(num: number, decimals = 0): string { * @returns A string formatted as USD. A number with 2 decimal places. * @note USD only has 2 decimal places of precision, so this will round to the nearest cent. */ -export function formatUSD(value: BigNumberish): string { - const formattedString = ethers.utils.formatUnits(value, 18); +export function formatUSD(value: BigNumberish, decimals = 18): string { + const formattedString = ethers.utils.formatUnits(value, decimals); return numeral(Number(formattedString).toFixed(2)).format("0,0.00"); } +export function formatUSDString(value: string, decimals = 2): string { + return `$${numeral(Number(value).toFixed(decimals)).format("0,0.00")}`; +} + /** * A fault-tolerant version of `parseUnits` that will attempt to parse * a string while being mindful of truncation. diff --git a/src/utils/getSwapChains.ts b/src/utils/getSwapChains.ts new file mode 100644 index 000000000..7a57c2691 --- /dev/null +++ b/src/utils/getSwapChains.ts @@ -0,0 +1,26 @@ +import mainnetChains from "../data/chains_1.json"; +import indirectChains from "../data/indirect_chains_1.json"; + +export type SwapChain = { + chainId: number; + name: string; + publicRpcUrl: string; + explorerUrl: string; + logoUrl: string; +}; + +/** + * Get swap chains data by combining mainnet and indirect chains + * This mimics the logic from api/swap/chains/index.ts for faster frontend access + */ +export function getSwapChains(): SwapChain[] { + const chains = mainnetChains; + + return [...chains, ...indirectChains].map((chain) => ({ + chainId: chain.chainId, + name: chain.name, + publicRpcUrl: chain.publicRpcUrl, + explorerUrl: chain.explorerUrl, + logoUrl: chain.logoUrl, + })); +} diff --git a/src/utils/index.ts b/src/utils/index.ts index 03639f72f..ff0a45976 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -23,3 +23,4 @@ export * from "./url"; export * from "./sdk"; export * from "./hyperliquid"; export * from "./bignumber"; +export * from "./colors"; diff --git a/src/utils/serverless-api/mocked/index.ts b/src/utils/serverless-api/mocked/index.ts index e7aec8384..5ff8edc78 100644 --- a/src/utils/serverless-api/mocked/index.ts +++ b/src/utils/serverless-api/mocked/index.ts @@ -11,6 +11,9 @@ import { poolsApiCall } from "./pools.mocked"; import { swapQuoteApiCall } from "./swap-quote"; import { poolsUserApiCall } from "./pools-user.mocked"; import { swapApprovalApiCall } from "../prod/swap-approval"; +import { swapChainsApiCall } from "../prod/swap-chains"; +import { swapTokensApiCall } from "../prod/swap-tokens"; +import { userTokenBalancesMockedApiCall } from "./user-token-balances.mocked"; export const mockedEndpoints: ServerlessAPIEndpoints = { coingecko: coingeckoMockedApiCall, @@ -29,4 +32,7 @@ export const mockedEndpoints: ServerlessAPIEndpoints = { poolsUser: poolsUserApiCall, swapQuote: swapQuoteApiCall, swapApproval: swapApprovalApiCall, + swapChains: swapChainsApiCall, + swapTokens: swapTokensApiCall, + userTokenBalances: userTokenBalancesMockedApiCall, }; diff --git a/src/utils/serverless-api/mocked/swap-approval.ts b/src/utils/serverless-api/mocked/swap-approval.ts index 4a09365c1..97bd8e43c 100644 --- a/src/utils/serverless-api/mocked/swap-approval.ts +++ b/src/utils/serverless-api/mocked/swap-approval.ts @@ -20,7 +20,30 @@ export async function swapApprovalApiCall( params.outputToken ); + const inputTokenInfo = { + address: params.inputToken, + chainId: params.originChainId, + decimals: inputToken?.decimals ?? 18, + symbol: inputToken?.symbol ?? "UNKNOWN", + }; + + const outputTokenInfo = { + address: params.outputToken, + chainId: params.destinationChainId, + decimals: outputToken?.decimals ?? 18, + symbol: outputToken?.symbol ?? "UNKNOWN", + }; + + const nativeTokenInfo = { + chainId: params.originChainId, + address: "0x0000000000000000000000000000000000000000", + decimals: 18, + symbol: "ETH", + }; + return { + crossSwapType: "BRIDGEABLE_TO_BRIDGEABLE", + amountType: params.tradeType || "exactInput", checks: { allowance: { token: params.inputToken, @@ -40,21 +63,12 @@ export async function swapApprovalApiCall( bridge: { inputAmount: BigNumber.from("0"), outputAmount: BigNumber.from("0"), - tokenIn: { - address: params.inputToken, - chainId: params.originChainId, - decimals: inputToken?.decimals ?? 18, - symbol: inputToken?.symbol ?? "UNKNOWN", - }, - tokenOut: { - address: params.outputToken, - chainId: params.destinationChainId, - decimals: outputToken?.decimals ?? 18, - symbol: outputToken?.symbol ?? "UNKNOWN", - }, + tokenIn: inputTokenInfo, + tokenOut: outputTokenInfo, fees: { amount: BigNumber.from("0"), pct: BigNumber.from("0"), + token: inputTokenInfo, details: { type: "across", lp: { @@ -71,9 +85,12 @@ export async function swapApprovalApiCall( }, }, }, + provider: "across", }, destinationSwap: undefined, }, + inputToken: inputTokenInfo, + outputToken: outputTokenInfo, refundToken: { address: params.inputToken, chainId: params.originChainId, @@ -81,6 +98,7 @@ export async function swapApprovalApiCall( symbol: params.inputToken, }, inputAmount: BigNumber.from(params.amount), + maxInputAmount: BigNumber.from(params.amount), expectedOutputAmount: BigNumber.from(params.amount), minOutputAmount: BigNumber.from(params.amount), expectedFillTime: 1, @@ -94,5 +112,110 @@ export async function swapApprovalApiCall( maxFeePerGas: BigNumber.from("0"), maxPriorityFeePerGas: BigNumber.from("0"), }, + fees: { + total: { + amount: BigNumber.from("0"), + amountUsd: "0", + pct: BigNumber.from("0"), + token: outputTokenInfo, + details: { + type: "TOTAL_BREAKDOWN", + swapImpact: { + amount: BigNumber.from("0"), + amountUsd: "0", + pct: BigNumber.from("0"), + token: inputTokenInfo, + }, + app: { + amount: BigNumber.from("0"), + amountUsd: "0", + pct: BigNumber.from("0"), + token: outputTokenInfo, + }, + bridge: { + amount: BigNumber.from("0"), + amountUsd: "0", + pct: BigNumber.from("0"), + token: inputTokenInfo, + details: { + type: "across", + lp: { + amount: BigNumber.from("0"), + amountUsd: "0", + pct: BigNumber.from("0"), + token: inputTokenInfo, + }, + relayerCapital: { + amount: BigNumber.from("0"), + amountUsd: "0", + pct: BigNumber.from("0"), + token: inputTokenInfo, + }, + destinationGas: { + amount: BigNumber.from("0"), + amountUsd: "0", + pct: BigNumber.from("0"), + token: nativeTokenInfo, + }, + }, + }, + }, + }, + totalMax: { + amount: BigNumber.from("0"), + amountUsd: "0", + pct: BigNumber.from("0"), + token: outputTokenInfo, + details: { + type: "MAX_TOTAL_BREAKDOWN", + maxSwapImpact: { + amount: BigNumber.from("0"), + amountUsd: "0", + pct: BigNumber.from("0"), + token: inputTokenInfo, + }, + app: { + amount: BigNumber.from("0"), + amountUsd: "0", + pct: BigNumber.from("0"), + token: outputTokenInfo, + }, + bridge: { + amount: BigNumber.from("0"), + amountUsd: "0", + pct: BigNumber.from("0"), + token: inputTokenInfo, + details: { + type: "across", + lp: { + amount: BigNumber.from("0"), + amountUsd: "0", + pct: BigNumber.from("0"), + token: inputTokenInfo, + }, + relayerCapital: { + amount: BigNumber.from("0"), + amountUsd: "0", + pct: BigNumber.from("0"), + token: inputTokenInfo, + }, + destinationGas: { + amount: BigNumber.from("0"), + amountUsd: "0", + pct: BigNumber.from("0"), + token: nativeTokenInfo, + }, + }, + }, + }, + }, + originGas: { + amount: BigNumber.from("0"), + amountUsd: "0", + token: nativeTokenInfo, + pct: BigNumber.from("0"), + }, + }, + eip712: undefined, }; } diff --git a/src/utils/serverless-api/mocked/user-token-balances.mocked.ts b/src/utils/serverless-api/mocked/user-token-balances.mocked.ts new file mode 100644 index 000000000..0d231fdc2 --- /dev/null +++ b/src/utils/serverless-api/mocked/user-token-balances.mocked.ts @@ -0,0 +1,48 @@ +import { UserTokenBalancesResponse } from "../types"; + +/** + * Mocked implementation of the user token balances API call + * @param account The Ethereum address to query token balances for + * @returns Mocked token balances data + */ +export async function userTokenBalancesMockedApiCall( + account: string +): Promise { + // Return mock data for testing/development + return { + account, + balances: [ + { + chainId: "1", + balances: [ + { + address: "0xA0b86a33E6441b8c4C8C0e4A0e4A0e4A0e4A0e4A0", + balance: "1000000000000000000", // 1 ETH + }, + { + address: "0xdAC17F958D2ee523a2206206994597C13D831ec7", + balance: "1000000000", // 1000 USDT + }, + ], + }, + { + chainId: "10", + balances: [ + { + address: "0x4200000000000000000000000000000000000006", + balance: "500000000000000000", // 0.5 WETH + }, + ], + }, + { + chainId: "137", + balances: [ + { + address: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", + balance: "2000000000", // 2000 USDC + }, + ], + }, + ], + }; +} diff --git a/src/utils/serverless-api/prod/index.ts b/src/utils/serverless-api/prod/index.ts index c885b478e..3dc618594 100644 --- a/src/utils/serverless-api/prod/index.ts +++ b/src/utils/serverless-api/prod/index.ts @@ -11,6 +11,9 @@ import { poolsApiCall } from "./pools"; import { swapQuoteApiCall } from "./swap-quote"; import { poolsUserApiCall } from "./pools-user"; import { swapApprovalApiCall } from "./swap-approval"; +import { swapChainsApiCall } from "./swap-chains"; +import { swapTokensApiCall } from "./swap-tokens"; +import { userTokenBalancesApiCall } from "./user-token-balances"; export const prodEndpoints: ServerlessAPIEndpoints = { coingecko: coingeckoApiCall, suggestedFees: suggestedFeesApiCall, @@ -28,4 +31,7 @@ export const prodEndpoints: ServerlessAPIEndpoints = { poolsUser: poolsUserApiCall, swapQuote: swapQuoteApiCall, swapApproval: swapApprovalApiCall, + swapChains: swapChainsApiCall, + swapTokens: swapTokensApiCall, + userTokenBalances: userTokenBalancesApiCall, }; diff --git a/src/utils/serverless-api/prod/swap-approval.ts b/src/utils/serverless-api/prod/swap-approval.ts index 781630ea2..f3f2c75a7 100644 --- a/src/utils/serverless-api/prod/swap-approval.ts +++ b/src/utils/serverless-api/prod/swap-approval.ts @@ -15,7 +15,37 @@ export type SwapApprovalApiReturnType = Awaited< ReturnType >; +type FeeComponent = { + amount: string; + amountUsd: string; + pct?: string; + token: SwapApiToken; +}; + +type AcrossBridgeFeeDetails = { + type: "across"; + lp: FeeComponent; + relayerCapital: FeeComponent; + destinationGas: FeeComponent; +}; + +type TotalFeeBreakdownDetails = { + type: "TOTAL_BREAKDOWN"; + swapImpact: FeeComponent; + app: FeeComponent; + bridge: FeeComponent & { details?: AcrossBridgeFeeDetails }; +}; + +type MaxTotalFeeBreakdownDetails = { + type: "MAX_TOTAL_BREAKDOWN"; + maxSwapImpact: FeeComponent; + app: FeeComponent; + bridge: FeeComponent & { details?: AcrossBridgeFeeDetails }; +}; + export type SwapApprovalApiResponse = { + crossSwapType: string; + amountType: string; checks: { allowance: { token: string; @@ -29,7 +59,8 @@ export type SwapApprovalApiResponse = { expected: string; }; }; - approvalTxns: { + approvalTxns?: { + chainId: number; to: string; data: string; }[]; @@ -41,6 +72,11 @@ export type SwapApprovalApiResponse = { outputAmount: string; minOutputAmount: string; maxInputAmount: string; + swapProvider: { + name: string; + sources: string[]; + }; + slippage: number; }; bridge: { inputAmount: string; @@ -50,6 +86,7 @@ export type SwapApprovalApiResponse = { fees: { amount: string; pct: string; + token: SwapApiToken; details: { type: "across"; lp: { @@ -66,6 +103,7 @@ export type SwapApprovalApiResponse = { }; }; }; + provider: string; }; destinationSwap?: { tokenIn: SwapApiToken; @@ -74,10 +112,18 @@ export type SwapApprovalApiResponse = { maxInputAmount: string; outputAmount: string; minOutputAmount: string; + swapProvider: { + name: string; + sources: string[]; + }; + slippage: number; }; }; + inputToken: SwapApiToken; + outputToken: SwapApiToken; refundToken: SwapApiToken; inputAmount: string; + maxInputAmount: string; expectedOutputAmount: string; minOutputAmount: string; expectedFillTime: number; @@ -86,11 +132,17 @@ export type SwapApprovalApiResponse = { chainId: number; to: string; data: string; - value: string; + value?: string; gas?: string; maxFeePerGas?: string; maxPriorityFeePerGas?: string; }; + fees?: { + total: FeeComponent & { details: TotalFeeBreakdownDetails }; + totalMax: FeeComponent & { details: MaxTotalFeeBreakdownDetails }; + originGas: FeeComponent; + }; + eip712?: any; }; export type SwapApprovalApiQueryParams = { @@ -119,7 +171,17 @@ export async function swapApprovalApiCall(params: SwapApprovalApiQueryParams) { const result = response.data; + // Helper function to convert fee component + const convertFeeComponent = (fee: FeeComponent) => ({ + amount: BigNumber.from(fee.amount), + amountUsd: fee.amountUsd, + pct: fee.pct ? BigNumber.from(fee.pct) : undefined, + token: fee.token, + }); + return { + crossSwapType: result.crossSwapType, + amountType: result.amountType, checks: { allowance: { token: result.checks.allowance.token, @@ -147,6 +209,8 @@ export async function swapApprovalApiCall(params: SwapApprovalApiQueryParams) { maxInputAmount: BigNumber.from( result.steps.originSwap.maxInputAmount ), + swapProvider: result.steps.originSwap.swapProvider, + slippage: result.steps.originSwap.slippage, } : undefined, bridge: { @@ -157,6 +221,7 @@ export async function swapApprovalApiCall(params: SwapApprovalApiQueryParams) { fees: { amount: BigNumber.from(result.steps.bridge.fees.amount), pct: BigNumber.from(result.steps.bridge.fees.pct), + token: result.steps.bridge.fees.token, details: { type: "across", lp: { @@ -183,6 +248,7 @@ export async function swapApprovalApiCall(params: SwapApprovalApiQueryParams) { }, }, }, + provider: result.steps.bridge.provider, }, destinationSwap: result.steps.destinationSwap ? { @@ -200,11 +266,16 @@ export async function swapApprovalApiCall(params: SwapApprovalApiQueryParams) { minOutputAmount: BigNumber.from( result.steps.destinationSwap.minOutputAmount ), + swapProvider: result.steps.destinationSwap.swapProvider, + slippage: result.steps.destinationSwap.slippage, } : undefined, }, + inputToken: result.inputToken, + outputToken: result.outputToken, refundToken: result.refundToken, inputAmount: BigNumber.from(result.inputAmount), + maxInputAmount: BigNumber.from(result.maxInputAmount), expectedOutputAmount: BigNumber.from(result.expectedOutputAmount), minOutputAmount: BigNumber.from(result.minOutputAmount), expectedFillTime: result.expectedFillTime, @@ -213,7 +284,9 @@ export async function swapApprovalApiCall(params: SwapApprovalApiQueryParams) { chainId: result.swapTx.chainId, to: result.swapTx.to, data: result.swapTx.data, - value: BigNumber.from(result.swapTx.value || "0"), + value: result.swapTx.value + ? BigNumber.from(result.swapTx.value) + : undefined, gas: result.swapTx.gas ? BigNumber.from(result.swapTx.gas) : undefined, maxFeePerGas: result.swapTx.maxFeePerGas ? BigNumber.from(result.swapTx.maxFeePerGas) @@ -222,5 +295,71 @@ export async function swapApprovalApiCall(params: SwapApprovalApiQueryParams) { ? BigNumber.from(result.swapTx.maxPriorityFeePerGas) : undefined, }, + fees: result.fees + ? { + total: { + ...convertFeeComponent(result.fees.total), + details: { + type: result.fees.total.details.type, + swapImpact: convertFeeComponent( + result.fees.total.details.swapImpact + ), + app: convertFeeComponent(result.fees.total.details.app), + bridge: { + ...convertFeeComponent(result.fees.total.details.bridge), + details: result.fees.total.details.bridge.details + ? { + type: result.fees.total.details.bridge.details.type, + lp: convertFeeComponent( + result.fees.total.details.bridge.details.lp + ), + relayerCapital: convertFeeComponent( + result.fees.total.details.bridge.details.relayerCapital + ), + destinationGas: convertFeeComponent( + result.fees.total.details.bridge.details.destinationGas + ), + } + : undefined, + }, + }, + }, + totalMax: { + ...convertFeeComponent(result.fees.totalMax), + details: { + type: result.fees.totalMax.details.type, + maxSwapImpact: convertFeeComponent( + result.fees.totalMax.details.maxSwapImpact + ), + app: convertFeeComponent(result.fees.totalMax.details.app), + bridge: { + ...convertFeeComponent(result.fees.totalMax.details.bridge), + details: result.fees.totalMax.details.bridge.details + ? { + type: result.fees.totalMax.details.bridge.details.type, + lp: convertFeeComponent( + result.fees.totalMax.details.bridge.details.lp + ), + relayerCapital: convertFeeComponent( + result.fees.totalMax.details.bridge.details + .relayerCapital + ), + destinationGas: convertFeeComponent( + result.fees.totalMax.details.bridge.details + .destinationGas + ), + } + : undefined, + }, + }, + }, + originGas: convertFeeComponent(result.fees.originGas), + } + : undefined, + eip712: result.eip712, }; } + +export type SwapApprovalApiCallReturnType = Awaited< + ReturnType +>; diff --git a/src/utils/serverless-api/prod/swap-chains.ts b/src/utils/serverless-api/prod/swap-chains.ts new file mode 100644 index 000000000..daccf8ea6 --- /dev/null +++ b/src/utils/serverless-api/prod/swap-chains.ts @@ -0,0 +1,12 @@ +import axios from "axios"; +import { vercelApiBaseUrl } from "utils"; +import { SwapChain } from "../types"; + +export type SwapChainsApiCall = typeof swapChainsApiCall; + +export async function swapChainsApiCall(): Promise { + const response = await axios.get( + `${vercelApiBaseUrl}/api/swap/chains` + ); + return response.data; +} diff --git a/src/utils/serverless-api/prod/swap-tokens.ts b/src/utils/serverless-api/prod/swap-tokens.ts new file mode 100644 index 000000000..e323b1604 --- /dev/null +++ b/src/utils/serverless-api/prod/swap-tokens.ts @@ -0,0 +1,21 @@ +import axios from "axios"; +import { vercelApiBaseUrl } from "utils"; +import { SwapToken } from "../types"; + +export type SwapTokensApiCall = typeof swapTokensApiCall; + +export type SwapTokensQuery = { + chainId?: number | number[]; +}; + +export async function swapTokensApiCall( + query?: SwapTokensQuery +): Promise { + const response = await axios.get( + `${vercelApiBaseUrl}/api/swap/tokens`, + { + params: query, + } + ); + return response.data; +} diff --git a/src/utils/serverless-api/prod/user-token-balances.ts b/src/utils/serverless-api/prod/user-token-balances.ts new file mode 100644 index 000000000..b9b2396da --- /dev/null +++ b/src/utils/serverless-api/prod/user-token-balances.ts @@ -0,0 +1,25 @@ +import axios from "axios"; +import { vercelApiBaseUrl } from "utils/constants"; +import { UserTokenBalancesResponse } from "../types"; + +export type UserTokenBalancesCall = typeof userTokenBalancesApiCall; + +/** + * Creates an HTTP call to the `user-token-balances` API endpoint + * @param account The Ethereum address to query token balances for + * @returns The result of the HTTP call to `api/user-token-balances` + */ +export async function userTokenBalancesApiCall( + account: string +): Promise { + const response = await axios.get( + `${vercelApiBaseUrl}/api/user-token-balances`, + { + params: { + account, + }, + } + ); + + return response.data; +} diff --git a/src/utils/serverless-api/types.ts b/src/utils/serverless-api/types.ts index ec196ea61..a5a66bd51 100644 --- a/src/utils/serverless-api/types.ts +++ b/src/utils/serverless-api/types.ts @@ -6,6 +6,9 @@ import { PoolsApiCall } from "./prod/pools"; import { SwapQuoteApiCall } from "./prod/swap-quote"; import { PoolsUserApiCall } from "./prod/pools-user"; import { SwapApprovalApiCall } from "./prod/swap-approval"; +import { SwapChainsApiCall } from "./prod/swap-chains"; +import { SwapTokensApiCall } from "./prod/swap-tokens"; +import { UserTokenBalancesCall } from "./prod/user-token-balances"; export type ServerlessAPIEndpoints = { coingecko: CoingeckoApiCall; @@ -24,6 +27,9 @@ export type ServerlessAPIEndpoints = { poolsUser: PoolsUserApiCall; swapQuote: SwapQuoteApiCall; swapApproval: SwapApprovalApiCall; + swapChains: SwapChainsApiCall; + swapTokens: SwapTokensApiCall; + userTokenBalances: UserTokenBalancesCall; }; export type RewardsApiFunction = @@ -111,3 +117,40 @@ export type BridgeLimitFunction = ( fromChainId: string | ChainId, toChainId: string | ChainId ) => Promise; + +export type SwapChain = { + chainId: number; + name: string; + publicRpcUrl: string; + explorerUrl: string; + logoUrl: string; +}; + +export type SwapToken = { + chainId: number; + address: string; + name: string; + symbol: string; + decimals: number; + logoUrl?: string; + priceUsd: string | null; +}; + +export interface UserTokenBalance { + address: string; + balance: string; +} + +export interface ChainBalances { + chainId: string; + balances: UserTokenBalance[]; +} + +export interface UserTokenBalancesResponse { + account: string; + balances: ChainBalances[]; +} + +export type UserTokenBalancesApiCall = ( + account: string +) => Promise; diff --git a/src/utils/token.ts b/src/utils/token.ts index 5a7df49d9..5dcf6fa0e 100644 --- a/src/utils/token.ts +++ b/src/utils/token.ts @@ -1,7 +1,23 @@ -import { ethers } from "ethers"; +import { BigNumber, ethers } from "ethers"; +import { LifiToken } from "hooks/useAvailableCrosschainRoutes"; -import { getProvider, ChainId, getConfig, getChainInfo } from "utils"; +import { + getProvider, + ChainId, + getConfig, + getChainInfo, + parseUnits, +} from "utils"; import { ERC20__factory } from "utils/typechain"; +import { SwapToken } from "utils/serverless-api/types"; +import { TokenInfo } from "constants/tokens"; +import { + CHAIN_IDs, + chainsWithUsdt0Enabled, + getToken, + tokenTable, +} from "utils/constants"; +import usdt0Logo from "assets/token-logos/usdt0.svg"; export async function getNativeBalance( chainId: ChainId, @@ -75,3 +91,132 @@ export function getExplorerLinkForToken( ) { return `${getChainInfo(tokenChainId).explorerUrl}/address/${tokenAddress}`; } + +// Standard precision for intermediate calculations (matches Ethereum wei) +const PRECISION = 18; + +/** + * Limits a decimal string to a maximum number of decimal places without losing precision + * @param value - The decimal string to limit + * @param maxDecimals - Maximum number of decimal places + * @returns The limited string + */ +function limitDecimals(value: string, maxDecimals: number): string { + const parts = value.split("."); + if (parts.length === 1) { + return value; // No decimal point + } + if (parts[1].length <= maxDecimals) { + return value; // Within limits + } + return parts[0] + "." + parts[1].substring(0, maxDecimals); +} + +/** + * Converts a token amount to USD value + * @param tokenAmount - The token amount as a string (decimal format) + * @param token - The token object containing price and decimals + * @returns The USD value as a BigNumber (18 decimals) + */ +export function convertTokenToUSD( + tokenAmount: string, + token: LifiToken +): BigNumber { + // Use 18 decimals for maximum precision in calculations + const normalizedAmount = limitDecimals(tokenAmount, PRECISION); + const tokenScaled = parseUnits(normalizedAmount, PRECISION); + const priceScaled = parseUnits(token.priceUSD, PRECISION); + return tokenScaled.mul(priceScaled).div(parseUnits("1", PRECISION)); +} + +/** + * Converts a USD amount to token amount + * @param usdAmount - The USD amount as a string (decimal format) + * @param token - The token object containing price and decimals + * @returns The token amount as a BigNumber (in token's native decimals) + */ +export function convertUSDToToken( + usdAmount: string, + token: LifiToken +): BigNumber { + // Use 18 decimals for maximum precision in calculations + const normalizedAmount = limitDecimals(usdAmount, PRECISION); + const usdScaled = parseUnits(normalizedAmount, PRECISION); + const priceScaled = parseUnits(token.priceUSD, PRECISION); + const result18Dec = usdScaled + .mul(parseUnits("1", PRECISION)) + .div(priceScaled); + + // Convert from 18 decimals to token's native decimals + const decimalDiff = PRECISION - token.decimals; + if (decimalDiff > 0) { + return result18Dec.div(BigNumber.from(10).pow(decimalDiff)); + } else if (decimalDiff < 0) { + return result18Dec.mul(BigNumber.from(10).pow(-decimalDiff)); + } + return result18Dec; +} + +/** + * Gets token info with chain-specific display modifications (temporary for USDT0) + * This is a temporary function that will be removed once all chains migrate to USDT0 + */ +export const getTokenForChain = ( + symbol: string, + chainId: number +): TokenInfo => { + const token = getToken(symbol); + + // Handle USDT -> USDT0 display for specific chains + if (token.symbol === "USDT" && chainsWithUsdt0Enabled.includes(chainId)) { + return { + ...token, + displaySymbol: "USDT0", + logoURI: usdt0Logo, + }; + } + + return token; +}; + +/** + * Attempts to coerce a SwapToken into a TokenInfo type + * Checks local token definitions to enrich with mainnetAddress and displaySymbol + * @param swapToken - The SwapToken to convert + * @returns A TokenInfo object with available properties mapped + */ +export function swapTokenToTokenInfo(swapToken: SwapToken): TokenInfo { + // Try to find the token in our local token definitions + const localToken = tokenTable?.[swapToken.symbol.toUpperCase()]; + + const baseTokenInfo: TokenInfo = { + name: swapToken.name, + symbol: swapToken.symbol, + decimals: swapToken.decimals, + logoURI: swapToken.logoUrl || "", + addresses: { + [swapToken.chainId]: swapToken.address, + }, + priceUsd: swapToken.priceUsd, + }; + + // If we found a local token definition, merge in mainnetAddress and displaySymbol + if (localToken) { + return { + ...baseTokenInfo, + mainnetAddress: localToken.mainnetAddress, + displaySymbol: localToken.displaySymbol, + logoURI: localToken.logoURI || baseTokenInfo.logoURI, // Prefer local logo if available + }; + } + + return baseTokenInfo; +} + +export function getTokenExplorerLinkFromAddress( + chainId: number, + address: string +) { + const explorerBaseUrl = getChainInfo(chainId).explorerUrl; + return `${explorerBaseUrl}/address/${address}`; +} diff --git a/src/views/Bridge/Bridge.tsx b/src/views/Bridge/Bridge.tsx index b6e03c545..948146487 100644 --- a/src/views/Bridge/Bridge.tsx +++ b/src/views/Bridge/Bridge.tsx @@ -4,12 +4,10 @@ import { LayoutV2 } from "components"; import { Wrapper } from "./Bridge.styles"; import Breadcrumb from "./components/Breadcrumb"; import BridgeForm from "./components/BridgeForm"; -import ChangeAccountModal from "./components/ChangeAccountModal"; import { useBridge } from "./hooks/useBridge"; -import { getEcosystem } from "utils"; const Bridge = () => { - const [displayChangeAccount, setDisplayChangeAccount] = useState(false); + const [_, setDisplayChangeAccount] = useState(false); const { selectedRoute, @@ -33,8 +31,6 @@ const Bridge = () => { universalSwapQuote, toAccountEVM, toAccountSVM, - handleChangeToAddressEVM, - handleChangeToAddressSVM, handleChangeAmountInput, handleClickMaxBalance, handleSelectInputToken, @@ -45,19 +41,8 @@ const Bridge = () => { isQuoteLoading, } = useBridge(); - const destinationChainEcosystem = getEcosystem(selectedRoute.toChain); - return ( <> - setDisplayChangeAccount(false)} - currentAccountEVM={toAccountEVM?.address} - currentAccountSVM={toAccountSVM?.address} - onChangeAccountEVM={handleChangeToAddressEVM} - onChangeAccountSVM={handleChangeToAddressSVM} - destinationChainEcosystem={destinationChainEcosystem} - /> diff --git a/src/views/Bridge/components/AmountInput.tsx b/src/views/Bridge/components/AmountInput.tsx index b3eb30c28..fc983e7ff 100644 --- a/src/views/Bridge/components/AmountInput.tsx +++ b/src/views/Bridge/components/AmountInput.tsx @@ -6,9 +6,9 @@ import { AmountInputError, SelectedRoute } from "../utils"; import { formatUnitsWithMaxFractions, getToken } from "utils"; import { BridgeLimits } from "hooks"; -const validationErrorTextMap: Record = { +export const validationErrorTextMap: Record = { [AmountInputError.INSUFFICIENT_BALANCE]: - "Insufficient balance to process this transfer.", + "Not enough [INPUT_TOKEN] to process this transfer.", [AmountInputError.PAUSED_DEPOSITS]: "[INPUT_TOKEN] deposits are temporarily paused.", [AmountInputError.INSUFFICIENT_LIQUIDITY]: @@ -20,6 +20,11 @@ const validationErrorTextMap: Record = { "Price impact is too high. Check back later when liquidity is restored.", [AmountInputError.SWAP_QUOTE_UNAVAILABLE]: "Swap quote temporarily unavailable. Please try again later.", + [AmountInputError.NO_INPUT_TOKEN_SELECTED]: + "Select an input token to continue", + [AmountInputError.NO_OUTPUT_TOKEN_SELECTED]: + "Select an output token to continue", + [AmountInputError.NO_AMOUNT_ENTERED]: "Enter an amount to continue", }; type Props = { diff --git a/src/views/Bridge/components/ChangeAccountModal.tsx b/src/views/Bridge/components/ChangeAccountModal.tsx index f48f5617a..9fcf7c626 100644 --- a/src/views/Bridge/components/ChangeAccountModal.tsx +++ b/src/views/Bridge/components/ChangeAccountModal.tsx @@ -1,60 +1,53 @@ import styled from "@emotion/styled"; -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { ethers } from "ethers"; import { isAddress as isSvmAddress } from "@solana/kit"; import { Modal, Text } from "components"; -import { PrimaryButton, UnstyledButton } from "components/Button"; +import { PrimaryButton } from "components/Button"; import { Input, InputGroup } from "components/Input"; import { ReactComponent as CrossIcon } from "assets/icons/cross.svg"; +import { ReactComponent as PencilIcon } from "assets/icons/pencil.svg"; + import { ampli } from "ampli"; import { useAmplitude } from "hooks"; import { useDisallowList } from "hooks/useDisallowList"; +import { COLORS, shortenAddress } from "utils"; +import { useHotkeys } from "react-hotkeys-hook"; +import { ToAccountManagement } from "../hooks/useToAccount"; type ChangeAccountModalProps = { - displayModal: boolean; - onCloseModal: () => void; - currentAccountEVM?: string; - currentAccountSVM?: string; - onChangeAccountEVM: (account: string) => void; - onChangeAccountSVM: (account: string) => void; + toAccountManagement: ToAccountManagement; destinationChainEcosystem: "evm" | "svm"; }; -const ChangeAccountModal = ({ - displayModal, - onCloseModal, - currentAccountEVM, - currentAccountSVM, - onChangeAccountEVM, - onChangeAccountSVM, +export const ChangeAccountModal = ({ + toAccountManagement, destinationChainEcosystem, }: ChangeAccountModalProps) => { - const [userInput, setUserInput] = useState( - destinationChainEcosystem === "evm" - ? currentAccountEVM || "" - : currentAccountSVM || "" - ); + const { + currentRecipientAccount, + handleChangeToAddressEVM, + handleChangeToAddressSVM, + defaultRecipientAccount, + } = toAccountManagement; + const inputRef = useRef(null); + const [displayModal, setDisplayModal] = useState(false); + const [userInput, setUserInput] = useState(currentRecipientAccount ?? ""); const [validInput, setValidInput] = useState(false); - const { isBlocked, isLoading } = useDisallowList(userInput); + const { isBlocked, isLoading } = useDisallowList(userInput ?? ""); const { addToAmpliQueue } = useAmplitude(); + const onCloseModal = () => setDisplayModal(false); + useEffect(() => { if (displayModal) { - setUserInput( - destinationChainEcosystem === "evm" - ? currentAccountEVM || "" - : currentAccountSVM || "" - ); + inputRef.current?.focus(); + setUserInput(currentRecipientAccount ?? ""); } - }, [ - currentAccountEVM, - currentAccountSVM, - displayModal, - destinationChainEcosystem, - ]); + }, [displayModal, currentRecipientAccount]); useEffect(() => { if (isLoading) { @@ -69,21 +62,14 @@ const ChangeAccountModal = ({ ? isValidAddressEVM : isValidAddressSVM ); - }, [ - currentAccountEVM, - currentAccountSVM, - userInput, - isBlocked, - isLoading, - destinationChainEcosystem, - ]); + }, [userInput, isBlocked, isLoading, destinationChainEcosystem]); const handleClickSave = () => { if (validInput || userInput === "") { if (destinationChainEcosystem === "evm") { - onChangeAccountEVM(userInput); + handleChangeToAddressEVM(userInput); } else { - onChangeAccountSVM(userInput); + handleChangeToAddressSVM(userInput); } addToAmpliQueue(() => { ampli.toAccountChanged({ @@ -104,19 +90,45 @@ const ChangeAccountModal = ({ const validationLevel = !validInput && !!userInput ? "error" : "valid"; + useHotkeys("esc", () => onCloseModal(), { enableOnFormTags: true }); + return ( - - - + <> + setDisplayModal(true)}> + <> + {currentRecipientAccount + ? shortenAddress(currentRecipientAccount, "..", 4) + : "Set Recipient"} + + + + + + + + Wallet Address + {defaultRecipientAccount && + userInput !== defaultRecipientAccount && ( + setUserInput(defaultRecipientAccount ?? "")} + > + Reset to Default + + )} + + setUserInput(t.target.value)} @@ -125,12 +137,14 @@ const ChangeAccountModal = ({ + + Note that only{" "} + + {destinationChainEcosystem === "evm" ? "Ethereum" : "Solana"} + {" "} + addresses are valid. + - - - Cancel - - - - - Note that only{" "} - - {destinationChainEcosystem === "evm" ? "Ethereum" : "Solana"} - {" "} - addresses are valid. - - - + + + ); }; -export default ChangeAccountModal; +const ResetButton = styled.button` + font-size: 14px; + color: ${COLORS.aqua}; + padding-block: 0px; +`; -const InnerWrapper = styled.div` - display: flex; - flex-direction: column; - align-items: flex-start; - padding: 0px; - gap: 24px; +const RowSpaced = styled.div` width: 100%; + display: flex; + justify-content: space-between; +`; + +const Trigger = styled.button` + color: var(--base-bright-gray, #e0f3ff); + + /* Body/Small */ + font-family: Barlow; + font-size: 14px; + font-style: normal; + font-weight: 400; + + display: inline-flex; + align-items: center; + gap: 4px; + opacity: 0.5; + + &:hover { + opacity: 1; + } +`; + +const SubHeading = styled.div` + color: var(--shades-Neutrals-neutral-400, #869099); + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 130%; +`; + +const Warning = styled.span` + color: var(--shades-Neutrals-neutral-400, #869099); + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 130%; + margin-top: 4px; + margin-bottom: 12px; `; const Wrapper = styled.div` display: flex; flex-direction: column; - gap: 24px; + gap: 12px; justify-content: flex-start; align-items: center; @@ -194,8 +239,8 @@ const StyledCrossIcon = styled(CrossIcon)` flex-shrink: 0; `; -const UnderlinedText = styled.span` - text-decoration: underline; +const BoldText = styled.span` + font-weight: 500; color: #e0f3ff; `; @@ -208,27 +253,6 @@ const ButtonWrapper = styled.div` width: 100%; `; -const CancelButton = styled(UnstyledButton)` - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - - width: 100%; - height: 64px; - - border: 1px solid #9daab3; - border-radius: 12px; - background: transparent; - - cursor: pointer; - - &:hover { - color: #e0f3ff; - border-color: #e0f3ff; - } -`; - const SaveButton = styled(PrimaryButton)` display: flex; flex-direction: row; diff --git a/src/views/Bridge/components/TokenFee.tsx b/src/views/Bridge/components/TokenFee.tsx index 837f0cc09..c29c27f61 100644 --- a/src/views/Bridge/components/TokenFee.tsx +++ b/src/views/Bridge/components/TokenFee.tsx @@ -4,7 +4,7 @@ import { AnimatePresence, motion } from "framer-motion"; import { useState } from "react"; import { Text, TextColor } from "components/Text"; -import { LoadingSkeleton } from "components"; +import { LoadingSkeleton, TokenImage } from "components"; import { formatUnitsWithMaxFractions, getExplorerLinkForToken, @@ -73,13 +73,13 @@ const TokenFee = ({ exit={{ y: "-100%" }} transition={{ duration: 0.2 }} > - + )} ) : ( - + )} ); @@ -96,7 +96,7 @@ const Wrapper = styled.div<{ invertDirection?: boolean }>` gap: 8px; `; -const TokenSymbol = styled.img` +const TokenSymbol = styled(TokenImage)` width: 16px; height: 16px; `; diff --git a/src/views/Bridge/components/TokenSelector.tsx b/src/views/Bridge/components/TokenSelector.tsx index 32c32679e..4e1598e92 100644 --- a/src/views/Bridge/components/TokenSelector.tsx +++ b/src/views/Bridge/components/TokenSelector.tsx @@ -2,7 +2,7 @@ import styled from "@emotion/styled"; import { useMemo } from "react"; import { ReactComponent as LinkExternalIcon } from "assets/icons/arrow-up-right-boxed.svg"; -import { Selector } from "components"; +import { Selector, TokenImage } from "components"; import { Text } from "components/Text"; import { TokenInfo, getTokenForChain, tokenList } from "utils"; @@ -125,7 +125,7 @@ export function TokenSelector({ }, element: ( - + {t.name} @@ -160,7 +160,7 @@ export function TokenSelector({ }))} displayElement={ - + {tokenToDisplay.displaySymbol || tokenToDisplay.symbol.toUpperCase()} @@ -192,7 +192,7 @@ const CoinIconTextWrapper = styled.div` gap: 12px; `; -const CoinIcon = styled.img` +const CoinIcon = styled(TokenImage)` width: 24px; height: 24px; `; diff --git a/src/views/Bridge/hooks/useBridgeAction/factory.ts b/src/views/Bridge/hooks/useBridgeAction/factory.ts index c67fdd39c..0a6fd06e9 100644 --- a/src/views/Bridge/hooks/useBridgeAction/factory.ts +++ b/src/views/Bridge/hooks/useBridgeAction/factory.ts @@ -174,7 +174,7 @@ export function createBridgeActionHook(strategy: BridgeActionStrategy) { statusPageSearchParams.set("integrator", existingIntegrator); } history.push( - `/bridge/${txHash}?${statusPageSearchParams}`, + `/bridge-and-swap/${txHash}?${statusPageSearchParams}`, // This state is stored in session storage and therefore persist // after a refresh of the deposit status page. { fromBridgePagePayload } diff --git a/src/views/Bridge/hooks/useToAccount.ts b/src/views/Bridge/hooks/useToAccount.ts index f978fd766..f2aaef8ad 100644 --- a/src/views/Bridge/hooks/useToAccount.ts +++ b/src/views/Bridge/hooks/useToAccount.ts @@ -10,6 +10,8 @@ export type ToAccount = { is7702Delegate: boolean; }; +export type ToAccountManagement = ReturnType; + export function useToAccount(toChainId?: number) { const [customToAddressEVM, setCustomToAddressEVM] = useState< string | undefined @@ -110,7 +112,19 @@ export function useToAccount(toChainId?: number) { setCustomToAddressSVM(address); }, []); + const defaultRecipientAccount = useMemo(() => { + return isDestinationSVM + ? connectedAccountSVM?.toBase58() + : connectedAccountEVM; + }, [connectedAccountEVM, connectedAccountSVM, isDestinationSVM]); + + const currentRecipientAccount = useMemo(() => { + return isDestinationSVM ? toAccountSVM?.address : toAccountEVM?.address; + }, [isDestinationSVM, toAccountEVM?.address, toAccountSVM?.address]); + return { + currentRecipientAccount, + defaultRecipientAccount, toAccountEVM, toAccountSVM, handleChangeToAddressEVM, diff --git a/src/views/Bridge/utils.ts b/src/views/Bridge/utils.ts index e65c63b95..3f9976299 100644 --- a/src/views/Bridge/utils.ts +++ b/src/views/Bridge/utils.ts @@ -53,6 +53,9 @@ export enum AmountInputError { AMOUNT_TOO_LOW = "amountTooLow", PRICE_IMPACT_TOO_HIGH = "priceImpactTooHigh", SWAP_QUOTE_UNAVAILABLE = "swapQuoteUnavailable", + NO_INPUT_TOKEN_SELECTED = "noInputTokenSelected", + NO_OUTPUT_TOKEN_SELECTED = "noOutputTokenSelected", + NO_AMOUNT_ENTERED = "noAmountEntered", } const config = getConfig(); const enabledRoutes = config.getEnabledRoutes(); diff --git a/src/views/DepositStatus/components/Breadcrumb.tsx b/src/views/DepositStatus/components/Breadcrumb.tsx index fff83d47e..e4d4230d7 100644 --- a/src/views/DepositStatus/components/Breadcrumb.tsx +++ b/src/views/DepositStatus/components/Breadcrumb.tsx @@ -11,6 +11,9 @@ type Props = { export function Breadcrumb({ depositTxHash }: Props) { return ( {shortenString(depositTxHash, "..", 4)} diff --git a/src/views/DepositStatus/components/DepositTimesCard.tsx b/src/views/DepositStatus/components/DepositTimesCard.tsx index ad0719aa7..45a706c9b 100644 --- a/src/views/DepositStatus/components/DepositTimesCard.tsx +++ b/src/views/DepositStatus/components/DepositTimesCard.tsx @@ -15,8 +15,6 @@ import { getBridgeUrlWithQueryParams, isDefined, formatUSD, - getToken, - getTokenForChain, } from "utils"; import { useAmplitude } from "hooks"; import { ampli } from "ampli"; @@ -32,6 +30,7 @@ import { getTokensForFeesCalc, } from "views/Bridge/utils"; import { useTokenConversion } from "hooks/useTokenConversion"; +import { useToken } from "hooks/useToken"; import EstimatedTable from "views/Bridge/components/EstimatedTable"; type Props = { @@ -73,19 +72,32 @@ export function DepositTimesCard({ const netFee = estimatedRewards?.netFeeAsBaseCurrency?.toString(); const amountSentBaseCurrency = amountAsBaseCurrency?.toString(); - const { inputToken, bridgeToken } = getTokensForFeesCalc({ - inputToken: getToken(inputTokenSymbol), - outputToken: getToken(outputTokenSymbol || inputTokenSymbol), - isUniversalSwap: isUniversalSwap, - universalSwapQuote: fromBridgePagePayload?.universalSwapQuote, - fromChainId: fromChainId, - toChainId: toChainId, - }); + const inputTokenFromHook = useToken(inputTokenSymbol); + const outputTokenFromHook = useToken(outputTokenSymbol || inputTokenSymbol); + const outputTokenForChain = useToken( + outputTokenSymbol || inputTokenSymbol, + toChainId + ); + + const { inputToken, bridgeToken } = + inputTokenFromHook && outputTokenFromHook + ? getTokensForFeesCalc({ + inputToken: inputTokenFromHook, + outputToken: outputTokenFromHook, + isUniversalSwap: isUniversalSwap, + universalSwapQuote: fromBridgePagePayload?.universalSwapQuote, + fromChainId: fromChainId, + toChainId: toChainId, + }) + : { + inputToken: inputTokenFromHook!, + bridgeToken: inputTokenFromHook!, + }; const { convertTokenToBaseCurrency: convertInputTokenToUsd } = - useTokenConversion(inputToken.symbol, "usd"); + useTokenConversion(inputToken?.symbol || inputTokenSymbol, "usd"); const { convertTokenToBaseCurrency: convertBridgeTokenToUsd } = - useTokenConversion(bridgeToken.symbol, "usd"); + useTokenConversion(bridgeToken?.symbol || inputTokenSymbol, "usd"); const { convertTokenToBaseCurrency: convertOutputTokenToUsd, convertBaseCurrencyToToken: convertUsdToOutputToken, @@ -184,16 +196,17 @@ export function DepositTimesCard({ )} {(netFee || amountSentBaseCurrency) && } - {isDefined(outputAmount) && - isDefined(outputTokenSymbol) && + + {isDefined(fromBridgePagePayload?.depositArgs?.initialAmount) && + inputToken && isDefined(amountSentBaseCurrency) && ( Amount sent )} - {isDefined(outputTokenSymbol) && ( + {isDefined(outputAmount) && + isDefined(outputTokenSymbol) && + outputTokenForChain && + isDefined(outputAmountUsd) && ( + + Amount received + + + (${formatUSD(outputAmountUsd)}) + + + )} + {isDefined(outputTokenSymbol) && outputTokenForChain && ( { + const token = useToken(inputTokenSymbol); const fromChain = getChainInfo(fromChainId).name; const toChain = getChainInfo(toChainId).name; - const amountSentText = amountSent - ? `~${formatUnitsWithMaxFractions(amountSent, getToken(inputTokenSymbol).decimals)}` - : undefined; + const amountSentText = + amountSent && token + ? `~${formatUnitsWithMaxFractions(amountSent, token.decimals)}` + : undefined; const shareText = [ `I just bridged ${amountSentText}${inputTokenSymbol} from ${fromChain} to ${toChain} using @AcrossProtocol.`, diff --git a/src/views/DepositStatus/hooks/useDepositTracking.ts b/src/views/DepositStatus/hooks/useDepositTracking.ts index ad0e3a710..7c49b505a 100644 --- a/src/views/DepositStatus/hooks/useDepositTracking.ts +++ b/src/views/DepositStatus/hooks/useDepositTracking.ts @@ -1,11 +1,10 @@ -import { useQuery } from "@tanstack/react-query"; +import { useQuery, useQueryClient } from "@tanstack/react-query"; import { useState, useEffect, useMemo } from "react"; import { BigNumber } from "ethers"; import { useAmplitude } from "hooks"; import { generateDepositConfirmed, - getToken, recordTransferUserProperties, wait, getChainInfo, @@ -25,6 +24,8 @@ import { DepositStatus } from "../types"; import { DepositData } from "./useDepositTracking/types"; import { useConnectionSVM } from "hooks/useConnectionSVM"; import { useConnectionEVM } from "hooks/useConnectionEVM"; +import { useToken } from "hooks/useToken"; +import { makeUseUserTokenBalancesQueryKey } from "hooks/useUserTokenBalances"; /** * Hook to track deposit and fill status across EVM and SVM chains @@ -48,12 +49,18 @@ export function useDepositTracking({ }) { const [shouldRetryDepositQuery, setShouldRetryDepositQuery] = useState(true); + const queryClient = useQueryClient(); const { addToAmpliQueue } = useAmplitude(); const { account: accountEVM } = useConnectionEVM(); const { account: accountSVM } = useConnectionSVM(); const account = getEcosystem(fromChainId) === "evm" ? accountEVM : accountSVM?.toBase58(); + // Resolve token info for analytics + const tokenForAnalytics = useToken( + fromBridgePagePayload?.quoteForAnalytics.tokenSymbol || "" + ); + // Create appropriate strategy for the source chain const { depositStrategy, fillStrategy } = useMemo( () => createChainStrategies(fromChainId, toChainId), @@ -167,9 +174,14 @@ export function useDepositTracking({ useEffect(() => { const fillInfo = fillQuery.data; - if (!fromBridgePagePayload || !fillInfo || fillInfo.status === "filling") { + if (!fillInfo || fillInfo.status === "filling") { return; } + // Refetch user balances + queryClient.refetchQueries({ + queryKey: makeUseUserTokenBalancesQueryKey(), + type: "all", // Refetch both active and inactive queries + }); // Remove existing deposit and add updated one with fill information const localDepositByTxHash = getLocalDepositByTxHash(depositTxHash); @@ -177,28 +189,44 @@ export function useDepositTracking({ removeLocalDeposits([depositTxHash]); } - // Add to local storage with fill information - // Use the strategy-specific conversion method - const localDeposit = fillStrategy.convertForFillQuery( - fillInfo, - fromBridgePagePayload - ); - addLocalDeposit(localDeposit); - - // Record transfer properties - const { quoteForAnalytics, depositArgs, tokenPrice } = - fromBridgePagePayload; - - recordTransferUserProperties( - BigNumber.from(depositArgs.amount), - BigNumber.from(tokenPrice), - getToken(quoteForAnalytics.tokenSymbol).decimals, - quoteForAnalytics.tokenSymbol.toLowerCase(), - Number(quoteForAnalytics.fromChainId), - Number(quoteForAnalytics.toChainId), - quoteForAnalytics.fromChainName - ); - }, [fillQuery.data, depositTxHash, fromBridgePagePayload, fillStrategy]); + if (fromBridgePagePayload) { + // Add to local storage with fill information + // Use the strategy-specific conversion method + const localDeposit = fillStrategy.convertForFillQuery( + fillInfo, + fromBridgePagePayload + ); + addLocalDeposit(localDeposit); + + // Record transfer properties + const { quoteForAnalytics, depositArgs, tokenPrice } = + fromBridgePagePayload; + + // Only record if we have token info + if (tokenForAnalytics) { + recordTransferUserProperties( + BigNumber.from(depositArgs.amount), + BigNumber.from(tokenPrice), + tokenForAnalytics.decimals, + quoteForAnalytics.tokenSymbol.toLowerCase(), + Number(quoteForAnalytics.fromChainId), + Number(quoteForAnalytics.toChainId), + quoteForAnalytics.fromChainName + ); + } + } + }, [ + fillQuery.data, + depositTxHash, + fromBridgePagePayload, + fillStrategy, + tokenForAnalytics, + queryClient, + fromChainId, + toChainId, + accountSVM, + accountEVM, + ]); const status: DepositStatus = !depositQuery.data?.depositTimestamp ? "depositing" diff --git a/src/views/DepositStatus/hooks/useDepositTracking/strategies/evm.ts b/src/views/DepositStatus/hooks/useDepositTracking/strategies/evm.ts index 673a5b2bc..a0a03f98f 100644 --- a/src/views/DepositStatus/hooks/useDepositTracking/strategies/evm.ts +++ b/src/views/DepositStatus/hooks/useDepositTracking/strategies/evm.ts @@ -292,11 +292,11 @@ export class EVMStrategy implements IChainStrategy { fromBridgePagePayload; const { depositId, depositor, recipient, message, inputAmount } = depositInfo.depositLog; - const inputToken = config.getTokenInfoBySymbol( + const inputToken = config.getTokenInfoBySymbolSafe( selectedRoute.fromChain, selectedRoute.fromTokenSymbol ); - const outputToken = config.getTokenInfoBySymbol( + const outputToken = config.getTokenInfoBySymbolSafe( selectedRoute.toChain, selectedRoute.toTokenSymbol ); @@ -361,11 +361,11 @@ export class EVMStrategy implements IChainStrategy { const { selectedRoute, depositArgs, quoteForAnalytics } = bridgePayload; const { depositId, depositor, recipient, message, inputAmount } = fillInfo.depositInfo.depositLog; - const inputToken = config.getTokenInfoBySymbol( + const inputToken = config.getTokenInfoBySymbolSafe( selectedRoute.fromChain, selectedRoute.fromTokenSymbol ); - const outputToken = config.getTokenInfoBySymbol( + const outputToken = config.getTokenInfoBySymbolSafe( selectedRoute.toChain, selectedRoute.toTokenSymbol ); diff --git a/src/views/DepositStatus/hooks/useDepositTracking/strategies/svm.ts b/src/views/DepositStatus/hooks/useDepositTracking/strategies/svm.ts index 7633d624a..f516bd9fe 100644 --- a/src/views/DepositStatus/hooks/useDepositTracking/strategies/svm.ts +++ b/src/views/DepositStatus/hooks/useDepositTracking/strategies/svm.ts @@ -196,11 +196,11 @@ export class SVMStrategy implements IChainStrategy { fromBridgePagePayload; const { depositId, depositor, recipient, message, inputAmount } = depositInfo.depositLog; - const inputToken = config.getTokenInfoBySymbol( + const inputToken = config.getTokenInfoBySymbolSafe( selectedRoute.fromChain, selectedRoute.fromTokenSymbol ); - const outputToken = config.getTokenInfoBySymbol( + const outputToken = config.getTokenInfoBySymbolSafe( selectedRoute.toChain, selectedRoute.toTokenSymbol ); @@ -266,11 +266,11 @@ export class SVMStrategy implements IChainStrategy { const { selectedRoute, depositArgs, quoteForAnalytics } = bridgePayload; const { depositId, depositor, recipient, message, inputAmount } = fillInfo.depositInfo.depositLog; - const inputToken = config.getTokenInfoBySymbol( + const inputToken = config.getTokenInfoBySymbolSafe( selectedRoute.fromChain, selectedRoute.fromTokenSymbol ); - const outputToken = config.getTokenInfoBySymbol( + const outputToken = config.getTokenInfoBySymbolSafe( selectedRoute.toChain, selectedRoute.toTokenSymbol ); diff --git a/src/views/DepositStatus/hooks/useResolveFromBridgePagePayload.ts b/src/views/DepositStatus/hooks/useResolveFromBridgePagePayload.ts index 8e561b3fc..c3e29b56f 100644 --- a/src/views/DepositStatus/hooks/useResolveFromBridgePagePayload.ts +++ b/src/views/DepositStatus/hooks/useResolveFromBridgePagePayload.ts @@ -1,4 +1,3 @@ -import { getToken } from "utils"; import { useEstimatedRewards } from "views/Bridge/hooks/useEstimatedRewards"; import { calcFeesForEstimatedTable, @@ -7,6 +6,7 @@ import { import { FromBridgePagePayload } from "views/Bridge/hooks/useBridgeAction"; import { useTokenConversion } from "hooks/useTokenConversion"; +import { useToken } from "hooks/useToken"; import { bigNumberifyObject } from "utils/bignumber"; import { UniversalSwapQuote } from "hooks/useUniversalSwapQuote"; import { SwapQuoteApiResponse } from "utils/serverless-api/prod/swap-quote"; @@ -31,27 +31,32 @@ export function useResolveFromBridgePagePayload( const isSwap = selectedRoute?.type === "swap"; const isUniversalSwap = selectedRoute?.type === "universal-swap"; - const swapToken = isSwap - ? getToken(selectedRoute.swapTokenSymbol) - : undefined; - const outputToken = getToken(outputTokenSymbol); - const { inputToken, bridgeToken } = getTokensForFeesCalc({ - inputToken: getToken(inputTokenSymbol), - outputToken, - isUniversalSwap: !!universalSwapQuote, - universalSwapQuote, - fromChainId: fromChainId, - toChainId: toChainId, - }); + const swapTokenSymbol = isSwap ? selectedRoute.swapTokenSymbol : ""; + + const swapToken = useToken(swapTokenSymbol); + const outputToken = useToken(outputTokenSymbol); + const inputTokenFromHook = useToken(inputTokenSymbol); + + const { inputToken, bridgeToken } = + inputTokenFromHook && outputToken + ? getTokensForFeesCalc({ + inputToken: inputTokenFromHook, + outputToken, + isUniversalSwap: !!universalSwapQuote, + universalSwapQuote, + fromChainId: fromChainId, + toChainId: toChainId, + }) + : { inputToken: inputTokenFromHook!, bridgeToken: inputTokenFromHook! }; const { convertTokenToBaseCurrency: convertInputTokenToUsd } = - useTokenConversion(inputToken.symbol, "usd"); + useTokenConversion(inputToken?.symbol || inputTokenSymbol, "usd"); const { convertTokenToBaseCurrency: convertBridgeTokenToUsd, convertBaseCurrencyToToken: convertUsdToBridgeToken, - } = useTokenConversion(bridgeToken.symbol, "usd"); + } = useTokenConversion(bridgeToken?.symbol || inputTokenSymbol, "usd"); const { convertTokenToBaseCurrency: convertOutputTokenToUsd } = - useTokenConversion(outputToken.symbol, "usd"); + useTokenConversion(outputToken?.symbol || outputTokenSymbol, "usd"); const { bridgeFeeUsd, @@ -82,7 +87,7 @@ export function useResolveFromBridgePagePayload( const capitalFee = convertUsdToBridgeToken(capitalFeeUsd); const estimatedRewards = useEstimatedRewards( - bridgeToken, + bridgeToken!, toChainId, isSwap || isUniversalSwap, parsedAmount, diff --git a/src/views/Rewards/components/ChainLogoOverlap.tsx b/src/views/Rewards/components/ChainLogoOverlap.tsx index 492f7bba3..2db670bc4 100644 --- a/src/views/Rewards/components/ChainLogoOverlap.tsx +++ b/src/views/Rewards/components/ChainLogoOverlap.tsx @@ -1,5 +1,6 @@ import styled from "@emotion/styled"; import { Tooltip } from "components/Tooltip"; +import { TokenImage } from "components/TokenImage"; import { COLORS, getChainInfo, rewardProgramTypes } from "utils"; import { useRewardProgramCard } from "../hooks/useRewardProgramCard"; @@ -14,7 +15,9 @@ const ChainLogoOverlap = ({ program }: { program: rewardProgramTypes }) => { } const tooltipTitle = `${rewardTokenSymbol} Reward eligible routes`; - const tooltipIcon = ; + const tooltipIcon = ( + + ); return ( { ))} @@ -53,7 +57,7 @@ const ChainOverlapWrapper = styled(Tooltip)` align-items: flex-start; `; -const ChainLogo = styled.img<{ zIndex: number }>` +const ChainLogo = styled(TokenImage)<{ zIndex: number }>` height: 18px; width: 18px; border-radius: 50%; @@ -62,7 +66,7 @@ const ChainLogo = styled.img<{ zIndex: number }>` margin-left: -10px; `; -const ChainTooltipIcon = styled.img` +const ChainTooltipIcon = styled(TokenImage)` width: 16px; height: 16px; diff --git a/src/views/Rewards/components/OverviewSection.tsx b/src/views/Rewards/components/OverviewSection.tsx index 271adc0c6..2d1720748 100644 --- a/src/views/Rewards/components/OverviewSection.tsx +++ b/src/views/Rewards/components/OverviewSection.tsx @@ -12,7 +12,7 @@ import { } from "utils"; import GenericOverviewCard from "./GenericOverviewCard"; import { useRewardProgramCard } from "../hooks/useRewardProgramCard"; -import { Text } from "components"; +import { Text, TokenImage } from "components"; import { BigNumber } from "ethers"; import { useHistory } from "react-router-dom"; import ChainLogoOverlap from "./ChainLogoOverlap"; @@ -213,7 +213,7 @@ const LogoContainer = styled.div<{ primaryColor: string; smallLogo?: boolean }>` 0px 2px 6px 0px rgba(0, 0, 0, 0.08); `; -const Logo = styled.img<{ smallLogo: boolean }>` +const Logo = styled(TokenImage)<{ smallLogo: boolean }>` height: ${({ smallLogo }) => (smallLogo ? 16 : 24)}px; width: ${({ smallLogo }) => (smallLogo ? 16 : 24)}px; `; diff --git a/src/views/Rewards/components/RewardProgramCard.tsx b/src/views/Rewards/components/RewardProgramCard.tsx index 042e4f6dd..31aa49dd1 100644 --- a/src/views/Rewards/components/RewardProgramCard.tsx +++ b/src/views/Rewards/components/RewardProgramCard.tsx @@ -5,7 +5,7 @@ import { formatUnitsWithMaxFractions, rewardProgramTypes, } from "utils"; -import { Text } from "components"; +import { Text, TokenImage } from "components"; import { ReactComponent as ChevronRight } from "assets/icons/chevron-right.svg"; import { useRewardProgramCard } from "../hooks/useRewardProgramCard"; import { Link } from "react-router-dom"; @@ -72,7 +72,7 @@ const Wrapper = styled.div<{ primaryColor: string; backgroundUrl: string }>` } `; -const Logo = styled.img` +const Logo = styled(TokenImage)` height: 24px; width: 24px; `; diff --git a/src/views/SwapAndBridge/components/BalanceSelector.tsx b/src/views/SwapAndBridge/components/BalanceSelector.tsx new file mode 100644 index 000000000..8212c87c7 --- /dev/null +++ b/src/views/SwapAndBridge/components/BalanceSelector.tsx @@ -0,0 +1,168 @@ +import { motion, AnimatePresence } from "framer-motion"; +import { useState, useMemo } from "react"; +import { BigNumber } from "ethers"; +import styled from "@emotion/styled"; +import { + COLORS, + formatUnitsWithMaxFractions, + compareAddressesSimple, +} from "utils"; +import { useUserTokenBalances } from "hooks/useUserTokenBalances"; + +type BalanceSelectorProps = { + token: { + chainId: number; + address: string; + decimals: number; + }; + setAmount: (amount: BigNumber | null) => void; + disableHover?: boolean; + error?: boolean; +}; + +export function BalanceSelector({ + token, + setAmount, + disableHover, + error = false, +}: BalanceSelectorProps) { + const [isHovered, setIsHovered] = useState(false); + const tokenBalances = useUserTokenBalances(); + + // Derive the balance from the latest token balances + const balance = useMemo(() => { + if (!tokenBalances.data?.balances) { + return BigNumber.from(0); + } + + const chainBalances = tokenBalances.data.balances.find( + (cb) => cb.chainId === String(token.chainId) + ); + + if (!chainBalances) { + return BigNumber.from(0); + } + + const tokenBalance = chainBalances.balances.find((b) => + compareAddressesSimple(b.address, token.address) + ); + + return tokenBalance?.balance + ? BigNumber.from(tokenBalance.balance) + : BigNumber.from(0); + }, [tokenBalances.data, token.chainId, token.address]); + + const percentages = ["25%", "50%", "75%", "MAX"]; + + const handlePillClick = (percentage: string) => { + if (percentage === "MAX") { + setAmount(balance); + } else { + const percent = parseInt(percentage) / 100; + const amount = balance.mul(Math.floor(percent * 10000)).div(10000); + setAmount(amount); + } + }; + + const formattedBalance = formatUnitsWithMaxFractions(balance, token.decimals); + + return ( + !disableHover && balance.gt(0) && setIsHovered(true)} + onMouseLeave={() => !disableHover && setIsHovered(false)} + > + + + {isHovered && + balance.gt(0) && + percentages.map((percentage, index) => ( + handlePillClick(percentage)} + > + {percentage} + + ))} + + + + Balance: {formattedBalance} + + + ); +} + +const BalanceWrapper = styled.div` + display: flex; + align-items: center; + gap: 12px; + margin-top: 8px; + position: relative; + justify-content: flex-end; + margin-left: auto; +`; + +const BalanceText = styled.div<{ error?: boolean }>` + color: ${({ error }) => + error ? COLORS.error : "var(--Base-bright-gray, #E0F3FF)"}; + opacity: 1; + font-size: 14px; + font-weight: 400; + line-height: 130%; + + span { + opacity: 0.5; + color: var(--Base-bright-gray, #e0f3ff); + } +`; + +const PillsContainer = styled.div` + --spacing: 4px; + display: flex; + align-items: center; + gap: var(--spacing); + position: absolute; + right: 100%; + padding-right: calc(var(--spacing) * 2); + + .pill { + display: flex; + height: 20px; + padding: 0 8px; + border-radius: 10px; + align-items: center; + justify-content: center; + font-size: 12px; + font-weight: 600; + border: 1px solid rgba(224, 243, 255, 0.5); + background-color: rgba(224, 243, 255, 0.05); + color: rgba(224, 243, 255, 0.5); + cursor: pointer; + user-select: none; + } +`; diff --git a/src/views/SwapAndBridge/components/ChainTokenSelector/ChainTokenSelectorModal.tsx b/src/views/SwapAndBridge/components/ChainTokenSelector/ChainTokenSelectorModal.tsx new file mode 100644 index 000000000..f433a3014 --- /dev/null +++ b/src/views/SwapAndBridge/components/ChainTokenSelector/ChainTokenSelectorModal.tsx @@ -0,0 +1,1372 @@ +import Modal from "components/Modal"; +import styled from "@emotion/styled"; +import { Searchbar } from "./Searchbar"; +import TokenMask from "assets/mask/token-mask-corner.svg"; +import { LifiToken } from "hooks/useAvailableCrosschainRoutes"; +import { + CHAIN_IDs, + ChainInfo, + COLORS, + formatUnitsWithMaxFractions, + formatUSD, + getChainInfo, + getTokenExplorerLinkFromAddress, + parseUnits, + QUERIES, + TOKEN_SYMBOLS_MAP, +} from "utils"; +import { useMemo, useState, useEffect, useRef } from "react"; +import { ReactComponent as CheckmarkCircleFilled } from "assets/icons/checkmark-circle-filled.svg"; +import { ReactComponent as ChevronRight } from "assets/icons/chevron-right.svg"; +import { ReactComponent as SearchResults } from "assets/icons/search_results.svg"; +import { ReactComponent as WarningIcon } from "assets/icons/warning_triangle.svg"; +import { ReactComponent as LinkExternalIcon } from "assets/icons/arrow-up-right-boxed.svg"; +import AllChainsIcon from "assets/chain-logos/all-swap-chain.png"; +import { useEnrichedCrosschainBalances } from "hooks/useEnrichedCrosschainBalances"; +import useCurrentBreakpoint from "hooks/useCurrentBreakpoint"; +import { BigNumber } from "ethers"; +import { Text, TokenImage } from "components"; +import { useHotkeys } from "react-hotkeys-hook"; + +const popularChains = [ + CHAIN_IDs.MAINNET, + CHAIN_IDs.BASE, + CHAIN_IDs.UNICHAIN, + CHAIN_IDs.ARBITRUM, + CHAIN_IDs.SOLANA, +]; + +const popularTokens = [ + TOKEN_SYMBOLS_MAP.USDC.symbol, + TOKEN_SYMBOLS_MAP.USDT.symbol, + TOKEN_SYMBOLS_MAP.ETH.symbol, + TOKEN_SYMBOLS_MAP.WETH.symbol, + TOKEN_SYMBOLS_MAP.WBTC.symbol, +]; + +type ChainData = ChainInfo & { + isDisabled: boolean; +}; + +type DisplayedChains = { + popular: ChainData[]; + all: ChainData[]; +}; + +export type EnrichedToken = LifiToken & { + balance: BigNumber; + balanceUsd: number; + routeSource: "bridge" | "swap"; +}; + +type EnrichedTokenWithReachability = EnrichedToken & { + isUnreachable: boolean; +}; + +type DisplayedTokens = { + popular: EnrichedTokenWithReachability[]; + all: EnrichedTokenWithReachability[]; +}; + +type Props = { + onSelect: (token: EnrichedToken) => void; + onSelectOtherToken?: (token: EnrichedToken | null) => void; // Callback to reset the other selector + isOriginToken: boolean; + currentToken?: EnrichedToken | null; // The currently selected token we're changing from + otherToken?: EnrichedToken | null; // The currently selected token on the other side + displayModal: boolean; + setDisplayModal: (displayModal: boolean) => void; +}; + +export function ChainTokenSelectorModal({ + isOriginToken, + displayModal, + setDisplayModal, + onSelect, + onSelectOtherToken, + currentToken, + otherToken, +}: Props) { + const crossChainRoutes = useEnrichedCrosschainBalances(); + const { isMobile } = useCurrentBreakpoint(); + + const [selectedChain, setSelectedChain] = useState( + currentToken?.chainId ?? popularChains[0] + ); + const [mobileStep, setMobileStep] = useState<"chain" | "token">("chain"); + + const [tokenSearch, setTokenSearch] = useState(""); + const [chainSearch, setChainSearch] = useState(""); + + // Reset mobile step when modal opens/closes + useEffect(() => { + setMobileStep("chain"); + setChainSearch(""); + setTokenSearch(""); + setSelectedChain(currentToken?.chainId ?? popularChains[0]); + }, [displayModal, currentToken]); + + const displayedTokens = useMemo(() => { + let tokens = selectedChain ? (crossChainRoutes[selectedChain] ?? []) : []; + + if (tokens.length === 0 && selectedChain === null) { + tokens = Object.values(crossChainRoutes).flatMap((t) => t); + } + + // Enrich tokens with route source information and unreachable flag + const enrichedTokens = tokens.map((token) => { + // Find the corresponding token in crossChainRoutes to get route source + const routeToken = crossChainRoutes?.[token.chainId]?.find( + (rt) => rt.address.toLowerCase() === token.address.toLowerCase() + ); + + // Token is unreachable if otherToken exists and is from the same chain + const isUnreachable = otherToken + ? token.chainId === otherToken.chainId + : false; + + return { + ...token, + routeSource: routeToken?.routeSource || "bridge", // Default to bridge if not found + isUnreachable, + }; + }); + + // Filter by search first + const filteredTokens = enrichedTokens.filter((t) => { + if (tokenSearch === "") { + return true; + } + // When a specific chain is selected, only show tokens from that chain + if (selectedChain !== null && t.chainId !== selectedChain) { + return false; + } + const keywords = [ + t.symbol.toLowerCase().replaceAll(" ", ""), + t.name.toLowerCase().replaceAll(" ", ""), + t.address.toLowerCase().replaceAll(" ", ""), + ]; + return keywords.some((keyword) => + keyword.includes(tokenSearch.toLowerCase().replaceAll(" ", "")) + ); + }); + + // Sort function that prioritizes tokens with balance, then by balance amount, then alphabetically + const sortTokens = (tokens: EnrichedTokenWithReachability[]) => { + return tokens.sort((a, b) => { + // Sort by token balance - tokens with balance go to top + const aHasTokenBalance = a.balance.gt(0); + const bHasTokenBalance = b.balance.gt(0); + + if (aHasTokenBalance !== bHasTokenBalance) { + return aHasTokenBalance ? -1 : 1; + } + + // If both have token balance, prioritize sorting by USD value if available + if (aHasTokenBalance && bHasTokenBalance) { + const aHasUsdBalance = a.balanceUsd > 0.01; + const bHasUsdBalance = b.balanceUsd > 0.01; + + // Both have USD values - sort by USD + if (aHasUsdBalance && bHasUsdBalance) { + if (Math.abs(b.balanceUsd - a.balanceUsd) < 0.0001) { + return a.symbol.toLocaleLowerCase().localeCompare(b.symbol); + } + return b.balanceUsd - a.balanceUsd; + } + + // Only one has USD value - prioritize the one with USD + if (aHasUsdBalance !== bHasUsdBalance) { + return aHasUsdBalance ? -1 : 1; + } + + // Neither has USD value - sort alphabetically + return a.symbol.toLocaleLowerCase().localeCompare(b.symbol); + } + + // If neither has balance, sort alphabetically + return a.symbol.toLocaleLowerCase().localeCompare(b.symbol); + }); + }; + + // When "all chains" is selected, don't separate popular tokens + if (selectedChain === null) { + const sortedAllTokens = sortTokens(filteredTokens); + return { + popular: [], // No popular section for all chains + all: sortedAllTokens, + }; + } + + // When a specific chain is selected, separate popular tokens from all tokens + const popularTokensList = filteredTokens.filter((token) => + popularTokens.includes(token.symbol) + ); + const allTokensList = filteredTokens.filter( + (token) => !popularTokens.includes(token.symbol) + ); + + // Sort both sections + const sortedPopularTokens = sortTokens(popularTokensList); + const sortedAllTokens = sortTokens(allTokensList); + + return { + popular: sortedPopularTokens, + all: sortedAllTokens, + }; + }, [selectedChain, crossChainRoutes, tokenSearch]); + + const displayedChains = useMemo(() => { + const chainsWithDisabledState = Object.keys(crossChainRoutes || {}) + .map((chainId) => getChainInfo(Number(chainId))) + .filter((chainInfo) => { + // TODO: check why we are filtering out Boba? + if (chainInfo.chainId === 288) { + return false; + } + + const keywords = [ + String(chainInfo.chainId), + chainInfo.name.toLowerCase().replace(" ", ""), + ]; + return keywords.some((keyword) => + keyword.toLowerCase().includes(chainSearch.toLowerCase()) + ); + }) + .map((chainInfo) => { + return { + ...chainInfo, + isDisabled: false, // No longer disable chains at chain level + }; + }); + + // Separate popular chains from all chains + const popularChainsData = chainsWithDisabledState + .filter((chain) => popularChains.includes(chain.chainId)) + .sort((chainA, chainB) => { + const indexA = popularChains.indexOf(Number(chainA.chainId)); + const indexB = popularChains.indexOf(Number(chainB.chainId)); + return indexA - indexB; + }); + + const allChainsData = chainsWithDisabledState + .filter((chain) => !popularChains.includes(chain.chainId)) + .sort((chainA, chainB) => { + const chainInfoA = getChainInfo(Number(chainA.chainId)); + const chainInfoB = getChainInfo(Number(chainB.chainId)); + return chainInfoA.name.localeCompare(chainInfoB.name); + }); + + return { + popular: popularChainsData, + all: allChainsData, + } as DisplayedChains; + }, [chainSearch, crossChainRoutes, otherToken]); + + return isMobile ? ( + { + setSelectedChain(chainId); + setMobileStep("token"); + }} + onTokenSelect={onSelect} + onSelectOtherToken={onSelectOtherToken} + /> + ) : ( + + ); +} + +// Mobile Modal Component +const MobileModal = ({ + isOriginToken, + displayModal, + setDisplayModal, + mobileStep, + setMobileStep, + selectedChain, + chainSearch, + setChainSearch, + tokenSearch, + setTokenSearch, + displayedChains, + displayedTokens, + onChainSelect, + onTokenSelect, + onSelectOtherToken, +}: { + isOriginToken: boolean; + displayModal: boolean; + setDisplayModal: (display: boolean) => void; + mobileStep: "chain" | "token"; + setMobileStep: (step: "chain" | "token") => void; + selectedChain: number | null; + chainSearch: string; + setChainSearch: (search: string) => void; + tokenSearch: string; + setTokenSearch: (search: string) => void; + displayedChains: DisplayedChains; + displayedTokens: DisplayedTokens; + onChainSelect: (chainId: number | null) => void; + onTokenSelect: (token: EnrichedToken) => void; + onSelectOtherToken?: (token: EnrichedToken | null) => void; +}) => { + return ( + + {mobileStep === "token" && ( + { + setMobileStep("chain"); + setTokenSearch(""); // Clear token search when going back + }} + > + + + )} + + {mobileStep === "chain" + ? `Select ${isOriginToken ? "Origin" : "Destination"} Chain` + : `Select ${isOriginToken ? "Origin" : "Destination"} Token`} + +
+ } + isOpen={displayModal} + padding="thin" + exitModalHandler={() => setDisplayModal(false)} + exitOnOutsideClick + width={400} + height={600} + titleBorder + noScroll + > + setDisplayModal(false)} + /> + + ); +}; + +// Desktop Modal Component +const DesktopModal = ({ + isOriginToken, + displayModal, + setDisplayModal, + selectedChain, + chainSearch, + setChainSearch, + tokenSearch, + setTokenSearch, + displayedChains, + displayedTokens, + onChainSelect, + onTokenSelect, + onSelectOtherToken, +}: { + isOriginToken: boolean; + displayModal: boolean; + setDisplayModal: (display: boolean) => void; + selectedChain: number | null; + chainSearch: string; + setChainSearch: (search: string) => void; + tokenSearch: string; + setTokenSearch: (search: string) => void; + displayedChains: DisplayedChains; + displayedTokens: DisplayedTokens; + onChainSelect: (chainId: number | null) => void; + onTokenSelect: (token: EnrichedToken) => void; + onSelectOtherToken?: (token: EnrichedToken | null) => void; +}) => { + return ( + Select {isOriginToken ? "Origin" : "Destination"} Token + } + isOpen={displayModal} + padding="thin" + exitModalHandler={() => setDisplayModal(false)} + exitOnOutsideClick + width={1100} + height={800} + titleBorder + noScroll + closeButtonTabIndex={99999} + > + setDisplayModal(false)} + /> + + ); +}; + +// Mobile Layout Component - 2-step process +const MobileLayout = ({ + isOriginToken, + mobileStep, + selectedChain, + chainSearch, + setChainSearch, + tokenSearch, + setTokenSearch, + displayedChains, + displayedTokens, + onChainSelect, + onTokenSelect, + onSelectOtherToken, + onModalClose, +}: { + isOriginToken: boolean; + mobileStep: "chain" | "token"; + selectedChain: number | null; + chainSearch: string; + setChainSearch: (search: string) => void; + tokenSearch: string; + setTokenSearch: (search: string) => void; + displayedChains: DisplayedChains; + displayedTokens: DisplayedTokens; + onChainSelect: (chainId: number | null) => void; + onTokenSelect: (token: EnrichedToken) => void; + onSelectOtherToken?: (token: EnrichedToken | null) => void; + onModalClose: () => void; +}) => { + const chainSearchInputRef = useRef(null); + const tokenSearchInputRef = useRef(null); + + // Focus chain search input when modal opens or when navigating back to chain step + useEffect(() => { + if (mobileStep === "chain") { + chainSearchInputRef.current?.focus(); + } else if (mobileStep === "token") { + tokenSearchInputRef.current?.focus(); + } + }, [mobileStep]); + + const warningMessage = "No Route"; + + return ( + + {mobileStep === "chain" ? ( + // Step 1: Chain Selection + + + + onChainSelect(null)} + /> + + {/* Popular Chains Section */} + {displayedChains.popular.length > 0 && ( + <> + Popular Chains + {displayedChains.popular.map(({ chainId, isDisabled }) => ( + onChainSelect(Number(chainId))} + /> + ))} + + )} + + {/* All Chains Section */} + + {displayedChains.all.length > 0 && ( + <> + All Chains + {displayedChains.all.map(({ chainId, isDisabled }) => ( + onChainSelect(Number(chainId))} + /> + ))} + + )} + + {!displayedChains.all.length && + !displayedChains.popular.length && + chainSearch && } + + + ) : ( + // Step 2: Token Selection + + + + {/* Popular Tokens Section */} + {displayedTokens.popular.length > 0 && ( + <> + Popular Tokens + {displayedTokens.popular.map((token) => ( + { + if (token.isUnreachable && onSelectOtherToken) { + onSelectOtherToken(null); + } + onTokenSelect(token); + onModalClose(); + }} + /> + ))} + + )} + + {/* All Tokens Section */} + + {displayedTokens.all.length > 0 && ( + <> + All Tokens + {displayedTokens.all.map((token) => ( + { + if (token.isUnreachable && onSelectOtherToken) { + onSelectOtherToken(null); + } + onTokenSelect(token); + onModalClose(); + }} + /> + ))} + + )} + {!displayedTokens.all.length && + !displayedTokens.popular.length && + tokenSearch && } + + + )} + + ); +}; + +// Desktop Layout Component - Side-by-side columns +const DesktopLayout = ({ + isOriginToken, + selectedChain, + chainSearch, + setChainSearch, + tokenSearch, + setTokenSearch, + displayedChains, + displayedTokens, + onChainSelect, + onTokenSelect, + onSelectOtherToken, + onModalClose, +}: { + isOriginToken: boolean; + selectedChain: number | null; + chainSearch: string; + setChainSearch: (search: string) => void; + tokenSearch: string; + setTokenSearch: (search: string) => void; + displayedChains: DisplayedChains; + displayedTokens: DisplayedTokens; + onChainSelect: (chainId: number | null) => void; + onTokenSelect: (token: EnrichedToken) => void; + onSelectOtherToken?: (token: EnrichedToken | null) => void; + onModalClose: () => void; +}) => { + const chainSearchInputRef = useRef(null); + const tokenSearchInputRef = useRef(null); + useHotkeys("esc", () => onModalClose(), { enableOnFormTags: true }); + + // Focus chain search input when component mounts + useEffect(() => { + chainSearchInputRef.current?.focus(); + }, []); + + function handleSelectChain(chainId: number | null): void { + onChainSelect(chainId); + tokenSearchInputRef.current?.focus(); + } + + const warningMessage = isOriginToken + ? "Output token will be reset" + : "Input token will be reset"; + + /** + * Tab order strategy for keyboard navigation: + * - Chain search: tabIndex 1 (always focused first) + * - Chain items: tabIndex 2-9999 range + * - "All Chains" entry: 2 + * - Popular chains: 3+ + * - All chains: follow after popular + * - Token search: tabIndex 10000 + * - Token items: tabIndex 10001+ range + * - Popular tokens: 10001+ + * - All tokens: follow after popular + * - Close button: tabIndex 99999 (always last) + */ + return ( + + + + + handleSelectChain(null)} + tabIndex={2} + /> + + {/* Popular Chains Section */} + {displayedChains.popular.length > 0 && ( + <> + Popular Chains + {displayedChains.popular.map(({ chainId, isDisabled }, index) => ( + handleSelectChain(chainId)} + tabIndex={3 + index} + /> + ))} + + )} + + {/* All Chains Section */} + {displayedChains.all.length > 0 && ( + <> + All Chains + {displayedChains.all.map(({ chainId, isDisabled }, index) => ( + handleSelectChain(chainId)} + tabIndex={3 + displayedChains.popular.length + index} + /> + ))} + + )} + {!displayedChains.all.length && + !displayedChains.popular.length && + chainSearch && } + + + + + + + {/* Popular Tokens Section */} + {displayedTokens.popular.length > 0 && ( + <> + Popular Tokens + {displayedTokens.popular.map((token, index) => ( + { + if (token.isUnreachable && onSelectOtherToken) { + onSelectOtherToken(null); + } + onTokenSelect(token); + onModalClose(); + }} + tabIndex={10001 + index} + /> + ))} + + )} + + {/* All Tokens Section */} + {displayedTokens.all.length > 0 && ( + <> + All Tokens + {displayedTokens.all.map((token, index) => ( + { + if (token.isUnreachable && onSelectOtherToken) { + onSelectOtherToken(null); + } + onTokenSelect(token); + onModalClose(); + }} + tabIndex={10001 + displayedTokens.popular.length + index} + /> + ))} + + )} + {!displayedTokens.all.length && + !displayedTokens.popular.length && + tokenSearch && } + + + + + Use shortcuts for fast navigation + + + Next itemtab + + + Selectreturn + + + Closeesc + + + + ); +}; + +const ChainEntry = ({ + chainId, + isSelected, + onClick, + isDisabled = false, + tabIndex, +}: { + chainId: number | null; + isSelected: boolean; + onClick: () => void; + isDisabled?: boolean; + tabIndex?: number; +}) => { + const chainInfo = chainId + ? getChainInfo(chainId) + : { + logoURI: AllChainsIcon, + name: "All", + }; + return ( + + + {chainInfo.name} + {isSelected && } + + ); +}; + +const TokenEntry = ({ + token, + isSelected, + onClick, + tabIndex, + warningMessage, +}: { + token: EnrichedTokenWithReachability; + isSelected: boolean; + onClick: () => void; + warningMessage: string; + tabIndex?: number; +}) => { + const hasTokenBalance = token.balance.gt(0); + const hasUsdBalance = token.balanceUsd >= 0.01; + + return ( + + + + + + {token.name} + + {token.symbol} + + + + {getChainInfo(token.chainId).name} + + + + {token.isUnreachable ? ( + + {" "} + {warningMessage} + + ) : ( +
+ )} + + {hasTokenBalance ? ( + + + {formatUnitsWithMaxFractions( + token.balance.toBigInt(), + token.decimals + )} + + + + {hasUsdBalance + ? "$" + formatUSD(parseUnits(token.balanceUsd.toString(), 18)) + : "-"} + + + ) : ( +
+ )} + + ); +}; + +const TokenItemImage = ({ token }: { token: LifiToken }) => { + return ( + + + + + ); +}; + +const EmptySearchResults = ({ + className, + query, +}: { + query: string; + className?: string; +}) => { + return ( + + + No results for {query} + + ); +}; + +const SearchResultsWrapper = styled.div` + display: flex; + flex-direction: column; + align-items: center; + gap: 24px; + color: white; + padding: 24px; +`; + +const SearchBarStyled = styled(Searchbar)` + flex-shrink: 0; +`; + +const TokenInfoWrapper = styled.div<{ dim?: boolean }>` + display: flex; + flex-direction: row; + justify-content: flex-start; + height: 100%; + align-items: center; + gap: 8px; + + opacity: ${({ dim }) => (dim ? 0.5 : 1)}; +`; + +const TokenItemImageWrapper = styled.div` + width: 32px; + height: 32px; + flex-shrink: 0; + position: relative; +`; + +const TokenItemTokenImage = styled(TokenImage)` + width: 100%; + height: 100%; + + top: 0; + left: 0; + + position: absolute; + + mask-image: url(${TokenMask}); + mask-size: 100% 100%; + mask-repeat: no-repeat; + mask-position: center; +`; + +const TokenItemChainImage = styled(TokenImage)` + width: 12px; + height: 12px; + + position: absolute; + + bottom: 0; + right: 0; +`; + +// Mobile Layout Styled Components +const MobileInnerWrapper = styled.div` + width: 100%; + height: 600px; /* Constrain height to enable scrolling */ + display: flex; + flex-direction: column; +`; + +const MobileChainWrapper = styled.div` + width: 100%; + display: flex; + flex-direction: column; + gap: 8px; + flex: 1; + min-height: 0; +`; + +const MobileTokenWrapper = styled.div` + width: 100%; + display: flex; + flex-direction: column; + gap: 8px; + flex: 1; + min-height: 0; +`; + +// Desktop Layout Styled Components +const DesktopInnerWrapper = styled.div` + width: 100%; + height: 800px; + display: flex; + flex-direction: row; + gap: 12px; +`; + +const DesktopChainWrapper = styled.div` + flex: 1; + display: flex; + flex-direction: column; + gap: 8px; + min-height: 0; + min-width: 230px; +`; + +const DesktopTokenWrapper = styled.div` + flex: 2; + display: flex; + flex-direction: column; + gap: 8px; + min-height: 0; +`; + +const VerticalDivider = styled.div` + width: 1px; + margin: -16px 0; + background-color: #3f4247; + flex-shrink: 0; +`; + +const TitleWrapper = styled.div` + display: flex; + align-items: center; + gap: 12px; + width: 100%; +`; + +const BackButton = styled.button` + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border: none; + background: transparent; + color: var(--base-bright-gray, #e0f3ff); + cursor: pointer; + border-radius: 6px; + transition: background 0.2s ease-in-out; + + &:hover { + background: rgba(255, 255, 255, 0.1); + } + + svg { + width: 16px; + height: 16px; + transform: rotate(180deg); /* Rotate chevron-right to make it point left */ + } +`; + +const Title = styled.div` + overflow: hidden; + color: var(--base-bright-gray, #e0f3ff); + font-family: Barlow; + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 130%; /* 26px */ + padding-left: 8px; + + ${QUERIES.tabletAndUp} { + font-size: 20px; + } +`; + +const ListWrapper = styled.div` + display: flex; + flex-direction: column; + gap: 4px; + overflow-y: auto; + flex: 1; + min-height: 0; + padding-bottom: calc( + 56px * 2 + 52px + ); // account for (56px - shortcuts footer) + + &::-webkit-scrollbar { + width: 8px; + } + + &::-webkit-scrollbar-track { + background: transparent; + } + + &::-webkit-scrollbar-thumb { + background: rgba(255, 255, 255, 0.1); + border-radius: 4px; + } + + &::-webkit-scrollbar-thumb:hover { + background: rgba(255, 255, 255, 0.2); + } + + scrollbar-width: thin; + scrollbar-color: rgba(255, 255, 255, 0.1) transparent; +`; + +const EntryItem = styled.button<{ isSelected: boolean; isDisabled?: boolean }>` + display: flex; + flex-direction: row; + justify-content: flex-start; + + width: 100%; + flex-shrink: 0; + + align-items: center; + + height: 48px; + gap: 8px; + + border-radius: 8px; + border: 2px solid transparent; + background: ${({ isSelected }) => + isSelected ? COLORS["aqua-5"] : "transparent"}; + + cursor: ${({ isDisabled }) => (isDisabled ? "not-allowed" : "pointer")}; + opacity: ${({ isDisabled }) => (isDisabled ? 0.5 : 1)}; + + &:hover { + background: ${({ isSelected, isDisabled }) => { + if (isDisabled) return "transparent"; + return isSelected ? COLORS["aqua-15"] : COLORS["grey-400-15"]; + }}; + } + + :focus-visible { + outline: none; + border-color: ${COLORS.aqua}; + } +`; + +const ChainEntryItem = EntryItem; + +const TokenEntryItem = styled(EntryItem)` + display: grid; + grid-template-columns: 3fr 2fr 1fr; // [TOKEN_INFO - WARNING - BALANCE] + gap: 8px; + align-items: center; +`; + +const ChainItemImage = styled.img` + width: 32px; + height: 32px; + flex-shrink: 0; +`; + +const ChainItemName = styled.div` + overflow: hidden; + color: var(--base-bright-gray, #e0f3ff); + text-overflow: ellipsis; + /* Body/Medium */ + font-family: Barlow; + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 130%; /* 20.8px */ +`; + +const ChainItemCheckmark = styled(CheckmarkCircleFilled)` + width: 20px; + height: 20px; + margin-left: auto; +`; + +const TokenNameSymbolWrapper = styled.div` + display: flex; + flex-direction: column; + width: 100%; + + align-items: flex-start; + justify-content: start; +`; + +const TokenSymbol = styled.div` + overflow: hidden; + color: var(--base-bright-gray, #e0f3ff); + text-overflow: ellipsis; + /* Body/X Small */ + font-family: Barlow; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 130%; /* 15.6px */ + + opacity: 0.5; +`; + +const TokenBalanceStack = styled.div<{ dim?: boolean }>` + display: flex; + flex-direction: column; + align-items: flex-end; + justify-content: center; + gap: 4px; + opacity: ${({ dim }) => (dim ? 0.5 : 1)}; +`; + +const TokenBalance = styled.div` + color: var(--base-bright-gray, #e0f3ff); + /* Body/Small */ + font-family: Barlow; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 130%; /* 18.2px */ +`; + +const TokenBalanceUsd = styled.div` + color: var(--base-bright-gray, #e0f3ff); + /* Body/X Small */ + font-family: Barlow; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 130%; /* 15.6px */ + opacity: 0.5; +`; + +const UnreachableWarning = styled.div` + color: var(--functional-red); + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 130%; + white-space: nowrap; + display: flex; + align-items: center; + justify-content: flex-end; + gap: 4px; +`; + +const SectionHeader = styled.div` + color: var(--base-bright-gray, #e0f3ff); + font-size: 14px; + font-weight: 400; + line-height: 130%; + opacity: 0.7; + padding: 8px 0px 4px 0px; + letter-spacing: 0.5px; +`; + +const KeyboardShortcutsTitle = styled.span` + margin-right: auto; +`; + +const KeyboardShortcutsSection = styled.div` + position: absolute; + bottom: 0; + left: 0; + height: 56px; + width: 100%; + border-top: 1px solid #34353b; + display: flex; + align-items: center; + justify-content: flex-end; + gap: 16px; + padding-inline: 24px; + margin-top: auto; + color: #e0f3ff7f; + background: #202024; +`; + +const KeyboardLegendItem = styled.div` + height: 100%; + display: flex; + align-items: center; + gap: 6px; +`; + +const Key = styled.div` + height: 24px; + border: 1px solid #34353b; + border-radius: 4px; + padding-inline: 8px; + font-size: 14px; + font-weight: 400; + display: flex; + align-items: center; + flex-shrink: 0; + color: rgba(224, 243, 255, 0.4); +`; + +const TokenName = styled.div` + overflow: hidden; + color: var(--base-bright-gray, #e0f3ff); + /* Body/Medium */ + font-family: Barlow; + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 130%; /* 20.8px */ + + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: inline-flex; + align-items: baseline; + gap: 4px; +`; + +const TokenLink = styled.a` + display: inline-flex; + flex-direction: row; + gap: 4px; + align-items: center; + text-decoration: none; + color: var(--base-bright-gray, #e0f3ff); + opacity: 0.5; + font-weight: 400; + + svg, + span { + font-size: 14px; + display: none; + color: inherit; + } + + &:hover { + text-decoration: underline; + color: ${COLORS.aqua}; + opacity: 1; + } + + &:hover { + svg { + display: inline; + } + } +`; diff --git a/src/views/SwapAndBridge/components/ChainTokenSelector/Searchbar.tsx b/src/views/SwapAndBridge/components/ChainTokenSelector/Searchbar.tsx new file mode 100644 index 000000000..d9ab65d0d --- /dev/null +++ b/src/views/SwapAndBridge/components/ChainTokenSelector/Searchbar.tsx @@ -0,0 +1,108 @@ +import styled from "@emotion/styled"; +import { ReactComponent as SearchIcon } from "assets/icons/search.svg"; +import { ReactComponent as ProductIcon } from "assets/icons/product.svg"; +import { COLORS } from "utils"; +import React from "react"; + +type Props = { + searchTopic: string; + search: string; + setSearch: (search: string) => void; + className?: string; + inputProps?: React.ComponentPropsWithoutRef<"input">; +}; + +export const Searchbar = React.forwardRef( + ({ searchTopic, search, setSearch, className, inputProps }, ref) => { + Searchbar.displayName = "Searchbar"; + return ( + + + setSearch(e.target.value)} + {...inputProps} + /> + {search ? setSearch("")} /> :
} + + ); + } +); + +const Wrapper = styled.div` + display: flex; + height: 44px; + padding: 0px 12px; + align-items: center; + gap: 8px; + flex-direction: row; + justify-content: space-between; + border: 2px solid transparent; + + border-radius: 8px; + background: transparent; + + width: 100%; + + &:hover, + &:active { + background: rgba(224, 243, 255, 0.05); + } + &:has(:focus-visible) { + border-color: ${COLORS.aqua}; + } + + &:focus-within { + background: rgba(224, 243, 255, 0.1); + } +`; + +const StyledSearchIcon = styled(SearchIcon)` + width: 20px; + height: 20px; + + flex-grow: 0; +`; + +const StyledProductIcon = styled(ProductIcon)` + width: 16px; + height: 16px; + + cursor: pointer; + + flex-grow: 0; +`; + +const Input = styled.input` + overflow: hidden; + color: var(--base-bright-gray, #e0f3ff); + text-overflow: ellipsis; + + &::placeholder { + color: #e0f3ff4d; + } + + &:hover, + &:active, + &:focus-visible { + color: ${COLORS.aqua}; + } + + background: transparent; + + border: none; + outline: none; + + width: 100%; + + /* Body/Medium */ + font-family: Barlow; + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 130%; /* 20.8px */ +`; diff --git a/src/views/SwapAndBridge/components/ChainTokenSelector/SelectorButton.tsx b/src/views/SwapAndBridge/components/ChainTokenSelector/SelectorButton.tsx new file mode 100644 index 000000000..c590fd174 --- /dev/null +++ b/src/views/SwapAndBridge/components/ChainTokenSelector/SelectorButton.tsx @@ -0,0 +1,207 @@ +import styled from "@emotion/styled"; +import { useCallback, useEffect, useState } from "react"; +import { COLORS, getChainInfo } from "utils"; +import { ReactComponent as ChevronDownIcon } from "assets/icons/chevron-down.svg"; +import { TokenImage } from "components/TokenImage"; +import { + ChainTokenSelectorModal, + EnrichedToken, +} from "./ChainTokenSelectorModal"; + +type Props = { + selectedToken: EnrichedToken | null; + onSelect?: (token: EnrichedToken) => void; + onSelectOtherToken?: (token: EnrichedToken | null) => void; // Callback to reset the other selector + isOriginToken: boolean; + otherToken?: EnrichedToken | null; // The currently selected token on the other side + marginBottom?: string; + className?: string; +}; + +export default function SelectorButton({ + onSelect, + onSelectOtherToken, + selectedToken, + isOriginToken, + otherToken, + className, +}: Props) { + const [displayModal, setDisplayModal] = useState(false); + + useEffect(() => { + if (selectedToken) { + onSelect?.(selectedToken); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedToken]); + + const setSelectedToken = useCallback( + (token: EnrichedToken) => { + onSelect?.(token); + setDisplayModal(false); + }, + [onSelect] + ); + + if (!selectedToken) { + return ( + <> + setDisplayModal(true)}> + + Select token + + + + + + + + + ); + } + + const chain = getChainInfo(selectedToken.chainId); + + return ( + <> + setDisplayModal(true)}> + + + + + + + {selectedToken.symbol} + {chain.name} + + + + + + + + + ); +} + +const Wrapper = styled.button` + --height: 48px; + --padding: 8px; + height: var(--height); + position: relative; + display: flex; + flex-direction: row; + justify-content: space-between; + + border-radius: 12px; + border: 1px solid rgba(224, 243, 255, 0.05); + background: rgba(224, 243, 255, 0.05); + + cursor: pointer; + + &:hover { + background: rgba(224, 243, 255, 0.1); + } +`; + +const VerticalDivider = styled.div` + width: 1px; + height: calc(100% - (var(--padding) * 2)); + margin-top: var(--padding); + + background: rgba(224, 243, 255, 0.05); +`; + +const ChevronStack = styled.div` + display: flex; + align-items: center; + justify-content: center; + height: 100%; + width: var(--height); +`; + +const NamesStack = styled.div` + display: flex; + flex-direction: column; + gap: 2px; + padding-inline: var(--padding); + white-space: nowrap; + height: 100%; + min-width: 72px; + + flex-grow: 1; + + justify-content: center; + align-items: flex-start; +`; + +const TokenName = styled.div` + font-size: 14px; + line-height: 100%; + font-weight: 600; + color: var(--base-bright-gray, #e0f3ff); +`; + +const SelectTokenName = styled(TokenName)` + color: ${COLORS["aqua"]}; + padding-inline: 8px; +`; + +const ChainName = styled.div` + font-size: 14px; + font-weight: 400; + line-height: 100%; + color: var(--base-bright-gray, #e0f3ff); + opacity: 0.5; +`; + +const TokenStack = styled.div` + height: 100%; + width: var(--height); + padding-inline: var(--padding); + position: relative; + flex-grow: 0; +`; + +const TokenImg = styled(TokenImage)` + border-radius: 50%; + position: absolute; + top: var(--padding); + left: var(--padding); + width: calc(var(--height) * 0.66); + height: calc(var(--height) * 0.66); + z-index: 1; +`; + +const ChainImg = styled(TokenImage)` + border-radius: 50%; + border: 1px solid transparent; + background: ${COLORS["grey-600"]}; + position: absolute; + bottom: calc(var(--padding) / 2); + right: calc(var(--padding) / 2); + width: 30%; + height: 30%; + z-index: 2; +`; + +const ChevronDown = styled(ChevronDownIcon)` + height: 16px; + width: 16px; +`; diff --git a/src/views/SwapAndBridge/components/ConfirmationButton.tsx b/src/views/SwapAndBridge/components/ConfirmationButton.tsx new file mode 100644 index 000000000..f33e8815f --- /dev/null +++ b/src/views/SwapAndBridge/components/ConfirmationButton.tsx @@ -0,0 +1,550 @@ +"use client"; +import { ButtonHTMLAttributes, useEffect } from "react"; +import { ReactComponent as ChevronDownIcon } from "assets/icons/chevron-down.svg"; +import { ReactComponent as LoadingIcon } from "assets/icons/loading-2.svg"; +import { ReactComponent as Info } from "assets/icons/info.svg"; +import { ReactComponent as Wallet } from "assets/icons/wallet.svg"; +import { ReactComponent as Across } from "assets/token-logos/acx.svg"; +import { ReactComponent as Route } from "assets/icons/route.svg"; +import { ReactComponent as Shield } from "assets/icons/shield.svg"; +import { ReactComponent as Dollar } from "assets/icons/dollar.svg"; +import { ReactComponent as Time } from "assets/icons/time.svg"; +import { ReactComponent as Warning } from "assets/icons/warning_triangle_filled.svg"; + +import React from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import { BigNumber } from "ethers"; +import { COLORS, formatUSDString, isDefined } from "utils"; +import { EnrichedToken } from "./ChainTokenSelector/ChainTokenSelectorModal"; +import styled from "@emotion/styled"; +import { Tooltip } from "components/Tooltip"; +import { SwapApprovalApiCallReturnType } from "utils/serverless-api/prod/swap-approval"; + +export type BridgeButtonState = + | "notConnected" + | "readyToConfirm" + | "submitting" + | "wrongNetwork" + | "loadingQuote" + | "validationError" + | "apiError"; + +interface ConfirmationButtonProps + extends ButtonHTMLAttributes { + inputToken: EnrichedToken | null; + outputToken: EnrichedToken | null; + amount: BigNumber | null; + swapQuote: SwapApprovalApiCallReturnType | null; + isQuoteLoading: boolean; + onConfirm?: () => Promise; + // External state props + buttonState: BridgeButtonState; + buttonDisabled: boolean; + buttonLoading: boolean; + buttonLabel?: string; +} + +// Expandable label section component +const ExpandableLabelSection: React.FC< + React.PropsWithChildren<{ + fee: string; + time: string; + expanded: boolean; + onToggle: () => void; + visible: boolean; + state: BridgeButtonState; + hasQuote: boolean; + }> +> = ({ fee, time, expanded, onToggle, state, children, hasQuote }) => { + // Render state-specific content + let content: React.ReactNode = null; + + const defaultState = ( + <> + + + Fast & Secure + + + Across V4. More Chains Faster. + + + ); + + // Show quote breakdown when quote is available, otherwise show default state + if (hasQuote) { + // Show quote details when available + content = ( + <> + + + Fast & Secure + + {!expanded && ( + + + + + + {fee} + + + + + + )} + + + ); + } else { + // Default state - show Across V4 branding + content = defaultState; + } + + return ( + <> + + {content} + + + {expanded && ( + + {children} + + )} + + + ); +}; + +// Core button component, used by all states +const ButtonCore: React.FC<{ + label: React.ReactNode; + loading?: boolean; + disabled?: boolean; + state: BridgeButtonState; + fullHeight?: boolean; + onClick?: () => void; +}> = ({ label, loading, disabled, state, onClick, fullHeight }) => ( + + + {loading && } + {state === "notConnected" && ( + + )} + {state === "apiError" && ( + + )} + {label} + + +); + +export const ConfirmationButton: React.FC = ({ + inputToken, + outputToken, + amount, + swapQuote, + onConfirm, + buttonState, + buttonDisabled, + buttonLoading, + buttonLabel, +}) => { + const [expanded, setExpanded] = React.useState(false); + + const state = buttonState; + + // Calculate display values from swapQuote + // Resolve conversion helpers outside memo to respect hooks rules + + const displayValues = React.useMemo(() => { + if (!swapQuote || !inputToken || !outputToken || !swapQuote.fees) { + return { + fee: "-", + time: "-", + bridgeFee: "-", + appFee: undefined, + swapImpact: undefined, + route: "Across V4", + estimatedTime: "-", + totalFee: "-", + }; + } + + const totalFeeUsd = swapQuote.fees.total.amountUsd; + const bridgeFeesUsd = swapQuote.fees.total.details.bridge.amountUsd; + const appFeesUsd = swapQuote.fees.total.details.app.amountUsd; + const swapImpactUsd = swapQuote.fees.total.details.swapImpact.amountUsd; + + // Only show fee items if they're at least 1 cent + const hasAppFee = Number(appFeesUsd) >= 0.01; + const hasSwapImpact = Number(swapImpactUsd) >= 0.01; + + const totalSeconds = Math.max(0, Number(swapQuote.expectedFillTime || 0)); + const underOneMinute = totalSeconds < 60; + const time = underOneMinute + ? `~${Math.max(1, Math.round(totalSeconds))} secs` + : `~${Math.ceil(totalSeconds / 60)} min`; + + return { + totalFee: formatUSDString(totalFeeUsd), + time, + bridgeFee: formatUSDString(bridgeFeesUsd), + appFee: hasAppFee ? formatUSDString(appFeesUsd) : undefined, + swapImpact: hasSwapImpact ? formatUSDString(swapImpactUsd) : undefined, + route: "Across V4", + estimatedTime: time, + }; + }, [swapQuote, inputToken, outputToken, amount]); + + // When notConnected, make button clickable so it can open wallet modal + const isButtonDisabled = state === "notConnected" ? false : buttonDisabled; + + useEffect(() => { + if (!swapQuote) { + setExpanded(false); + } + }, [swapQuote]); + + // Render unified group driven by state + const content = ( + <> + setExpanded((e) => !e)} + visible={true} + state={state} + hasQuote={!!swapQuote} + > + + + + + Route + + + + {displayValues.route} + + + + + + {displayValues.estimatedTime} + + + + + Total Fee + + + + + {displayValues.totalFee} + + + + + Bridge Fee + + + + + {displayValues.bridgeFee} + + {isDefined(displayValues.swapImpact) && ( + + + Swap Impact + + + + + + {displayValues.swapImpact} + + + )} + + + + + + ); + + return ( + + {content} + + ); +}; + +// Styled components +const Container = styled(motion.div)<{ dark: boolean }>` + background: ${({ dark }) => + dark ? COLORS["grey-400-5"] : "rgba(108, 249, 216, 0.1)"}; + border-radius: 24px; + display: flex; + flex-direction: column; + padding: 8px 12px 12px 12px; + width: 100%; + overflow: hidden; +`; + +const ExpandableLabelButton = styled.button` + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + padding: 8px; + padding-bottom: 16px; + background: transparent; + border: none; + cursor: pointer; + user-select: none; +`; + +const ExpandableLabelLeft = styled.span` + color: ${COLORS.aqua}; + font-weight: 600; + font-size: 14px; + flex: 1; + text-align: left; + display: flex; + align-items: center; + gap: 8px; + justify-content: flex-start; +`; + +const FastSecureText = styled.span` + color: ${COLORS.aqua}; +`; + +const ExpandableLabelRight = styled.div` + display: flex; + align-items: center; + gap: 8px; + font-size: 12px; + color: #e0f3ff; + justify-content: flex-end; +`; + +const ExpandableLabelRightAccent = styled(ExpandableLabelLeft)` + text-align: right; + justify-content: flex-end; +`; + +const FeeTimeItem = styled.span` + display: flex; + align-items: center; + gap: 4px; +`; + +const Divider = styled.span` + margin: 0 8px; + height: 16px; + width: 1px; + background: rgba(224, 243, 255, 0.5); +`; + +const StyledChevronDown = styled(ChevronDownIcon)<{ expanded: boolean }>` + width: 20px; + height: 20px; + margin-left: 12px; + transition: transform 0.2s ease; + cursor: pointer; + color: #e0f3ff; + transform: ${({ expanded }) => + expanded ? "rotate(180deg)" : "rotate(0deg)"}; +`; + +const StyledButton = styled.button<{ + aqua?: boolean; + loading?: boolean; + fullHeight?: boolean; +}>` + width: 100%; + height: 64px; + border-radius: 12px; + font-weight: 600; + font-size: 16px; + transition: + background 0.3s ease, + color 0.3s ease, + box-shadow 0.3s ease, + opacity 0.3s ease; + border: none; + cursor: pointer; + + background: ${({ aqua }) => + aqua ? COLORS.aqua : "rgba(224, 243, 255, 0.05)"}; + color: ${({ aqua }) => (aqua ? "#2D2E33" : "#E0F3FF")}; + + &:not(:disabled):hover { + box-shadow: ${({ aqua }) => + aqua + ? `0 0 10px 0 var(--Transparency-Bright-Gray-bright-gray-50, rgba(224, 243, 255, 0.50)) inset, 0 0 4px 2px var(--Transparency-Aqua-aqua-20, rgba(108, 249, 216, 0.20)), 0 2px 12px 1px var(--Transparency-Aqua-aqua-20, rgba(108, 249, 216, 0.20)), 0 4px 24px 2px var(--Transparency-Aqua-aqua-20, rgba(108, 249, 216, 0.20))` + : ` + `}; + } + + &:not(:disabled):focus { + ${({ aqua }) => !aqua && `box-shadow: 0 0 16px 0 ${COLORS.aqua};`} + } + + &:disabled { + cursor: ${({ loading }) => (loading ? "wait" : "not-allowed")}; + box-shadow: none; + opacity: ${({ loading }) => (loading ? 0.9 : 0.6)}; + } +`; + +const ButtonContent = styled.span` + display: flex; + align-items: center; + justify-content: center; + gap: 8px; +`; + +const StyledLoadingIcon = styled(LoadingIcon)` + width: 16px; + height: 16px; + animation: spin 1s linear infinite; + color: inherit; + + @keyframes spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } + } +`; + +const ExpandedDetails = styled.div` + color: rgba(224, 243, 255, 0.5); + font-size: 14px; + width: 100%; + padding: 8px 16px 24px; +`; + +const DetailRow = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 8px; +`; + +const DetailLeft = styled.div` + display: flex; + align-items: center; + gap: 4px; +`; + +const DetailRight = styled.div` + display: flex; + align-items: center; + gap: 8px; + color: #e0f3ff; +`; + +const FeeBreakdown = styled.div` + padding-left: 16px; + margin-left: 8px; + margin-top: 12px; +`; + +const FeeBreakdownRow = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 4px; + position: relative; + + &::before { + content: ""; + width: 10px; + height: 18px; + border-radius: 0 0 0 6px; + border-left: 1px solid currentColor; + border-bottom: 1px solid currentColor; + position: absolute; + left: -16px; + top: -0.5em; + opacity: 0.5; + } +`; + +const FeeBreakdownLabel = styled.span` + display: inline-flex; + align-items: center; + gap: 4px; + color: rgba(224, 243, 255, 0.5); +`; + +const FeeBreakdownValue = styled.span` + color: #e0f3ff; +`; diff --git a/src/views/SwapAndBridge/components/InputForm.tsx b/src/views/SwapAndBridge/components/InputForm.tsx new file mode 100644 index 000000000..d65818b7a --- /dev/null +++ b/src/views/SwapAndBridge/components/InputForm.tsx @@ -0,0 +1,433 @@ +import { COLORS, formatUSD, withOpacity } from "utils"; +import SelectorButton from "./ChainTokenSelector/SelectorButton"; +import { EnrichedToken } from "./ChainTokenSelector/ChainTokenSelectorModal"; +import { BalanceSelector } from "./BalanceSelector"; +import styled from "@emotion/styled"; +import { useCallback, useEffect, useRef, useState } from "react"; +import { BigNumber } from "ethers"; +import { ReactComponent as ArrowsCross } from "assets/icons/arrows-cross.svg"; +import { ReactComponent as ArrowDown } from "assets/icons/arrow-down.svg"; +import { AmountInputError } from "views/Bridge/utils"; +import { useTokenInput, UnitType } from "hooks"; +import { formatUnits } from "ethers/lib/utils"; +import { ChangeAccountModal } from "views/Bridge/components/ChangeAccountModal"; +import { ToAccountManagement } from "views/Bridge/hooks/useToAccount"; + +export const InputForm = ({ + inputToken, + outputToken, + setInputToken, + setOutputToken, + setAmount, + isAmountOrigin, + setIsAmountOrigin, + isQuoteLoading, + expectedOutputAmount, + expectedInputAmount, + validationError, + toAccountManagement, + destinationChainEcosystem, +}: { + inputToken: EnrichedToken | null; + setInputToken: (token: EnrichedToken | null) => void; + + outputToken: EnrichedToken | null; + setOutputToken: (token: EnrichedToken | null) => void; + + isQuoteLoading: boolean; + expectedOutputAmount: string | undefined; + expectedInputAmount: string | undefined; + + setAmount: (amount: BigNumber | null) => void; + + isAmountOrigin: boolean; + setIsAmountOrigin: (isAmountOrigin: boolean) => void; + validationError: AmountInputError | undefined; + toAccountManagement: ToAccountManagement; + destinationChainEcosystem: "evm" | "svm"; +}) => { + // Shared unit state for both inputs + const [unit, setUnit] = useState("token"); + + const quickSwap = useCallback(() => { + const origin = inputToken; + const destination = outputToken; + + setOutputToken(origin); + setInputToken(destination); + + setAmount(null); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [inputToken, outputToken]); + + return ( + + { + setAmount(amount); + setIsAmountOrigin(true); + }} + isOrigin={true} + expectedAmount={expectedInputAmount} + shouldUpdate={!isAmountOrigin} + isUpdateLoading={isQuoteLoading} + insufficientInputBalance={ + validationError === AmountInputError.INSUFFICIENT_BALANCE + } + otherToken={outputToken} + disabled={!outputToken || !outputToken} + unit={unit} + setUnit={setUnit} + toAccountManagement={toAccountManagement} + destinationChainEcosystem={destinationChainEcosystem} + /> + + + + { + setAmount(amount); + setIsAmountOrigin(false); + }} + isOrigin={false} + expectedAmount={expectedOutputAmount} + shouldUpdate={isAmountOrigin} + isUpdateLoading={isQuoteLoading} + otherToken={inputToken} + disabled={!outputToken || !outputToken} + unit={unit} + setUnit={setUnit} + toAccountManagement={toAccountManagement} + destinationChainEcosystem={destinationChainEcosystem} + /> + + ); +}; + +const TokenInput = ({ + setToken, + setOtherToken, + token, + setAmount, + isOrigin, + expectedAmount, + shouldUpdate, + isUpdateLoading, + insufficientInputBalance = false, + otherToken, + disabled, + unit, + setUnit, + toAccountManagement, + destinationChainEcosystem, +}: { + setToken: (token: EnrichedToken) => void; + setOtherToken: (token: EnrichedToken | null) => void; + token: EnrichedToken | null; + setAmount: (amount: BigNumber | null) => void; + isOrigin: boolean; + expectedAmount: string | undefined; + shouldUpdate: boolean; + isUpdateLoading: boolean; + insufficientInputBalance?: boolean; + disabled?: boolean; + otherToken?: EnrichedToken | null; + unit: UnitType; + setUnit: (unit: UnitType) => void; + toAccountManagement: ToAccountManagement; + destinationChainEcosystem: "evm" | "svm"; +}) => { + const amountInputRef = useRef(null); + const hasAutoFocusedRef = useRef(false); + + const { + amountString, + convertedAmount, + toggleUnit, + handleInputChange, + handleBalanceClick, + } = useTokenInput({ + token, + setAmount, + expectedAmount, + shouldUpdate, + isUpdateLoading, + unit, + setUnit, + }); + + const inputDisabled = (() => { + if (disabled) return true; + return Boolean(shouldUpdate && isUpdateLoading); + })(); + + useEffect(() => { + // Focus origin token amount input when it first becomes enabled + if ( + isOrigin && + !inputDisabled && + !hasAutoFocusedRef.current && + amountInputRef.current + ) { + amountInputRef.current.focus(); + hasAutoFocusedRef.current = true; + } + }, [isOrigin, inputDisabled]); + + const formattedConvertedAmount = (() => { + if (!convertedAmount) return "0.00"; + if (unit === "token") { + // convertTokenToUSD returns in 18 decimal precision + return "$" + formatUSD(convertedAmount); + } + // convertUSDToToken returns in token's native decimals + return `${formatUnits(convertedAmount, token?.decimals)} ${token?.symbol}`; + })(); + + return ( + + + + {isOrigin ? "From" : "To"} + {!isOrigin && ( + <> + + + )} + + + + handleInputChange(e.target.value)} + disabled={inputDisabled} + error={insufficientInputBalance} + /> + + + {" "} + Value: {formattedConvertedAmount} + + + + + + {token && ( + { + if (amount) { + handleBalanceClick(amount, token.decimals); + } + }} + /> + )} + + + ); +}; + +const TokenSelectorColumn = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 12px; +`; + +const ValueRow = styled.div` + font-size: 16px; + span { + margin-left: 4px; + } + span, + svg { + display: inline-block; + vertical-align: middle; + } +`; + +const UnitToggleButton = styled.button` + color: ${withOpacity("#e0f3ff", 0.5)}; + + display: inline-flex; + align-items: center; + gap: 4px; + + &:hover:not(:disabled) { + svg { + color: #e0f3ff; + } + } + + span { + color: inherit; + } + + svg { + color: inherit; + } +`; + +const TokenAmountStack = styled.div` + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: flex-start; + align-self: stretch; + + height: 100%; +`; + +const TokenAmountInputTitle = styled.div` + display: flex; + align-items: center; + gap: 8px; + color: ${COLORS.aqua}; + font-size: 16px; + font-weight: 500; + line-height: 130%; +`; + +const TokenAmountInputWrapper = styled.div<{ + showPrefix: boolean; + value: string; + error: boolean; +}>` + display: flex; + align-items: center; + width: 100%; + position: relative; + + font-size: 48px; + font-weight: 300; + line-height: 120%; + letter-spacing: -1.92px; + + color: ${({ value, error }) => + error ? COLORS.error : value ? COLORS.aqua : COLORS["light-200"]}; + + &:focus-within { + font-size: 48px; + } + + ${({ showPrefix, value, error }) => + showPrefix && + ` + &::before { + content: "$"; + margin-right: 4px; + flex-shrink: 0; + font-size: 48px; + font-weight: 300; + line-height: 120%; + letter-spacing: -1.92px; + color: ${error ? COLORS.error : value ? COLORS.aqua : "var(--base-bright-gray, #e0f3ff)"}; + opacity: ${value ? 1 : 0.5}; + } + `} +`; + +const TokenAmountInput = styled.input<{ + value: string; + error: boolean; +}>` + width: 100%; + outline: none; + border: none; + background: transparent; + font: inherit; + font-size: inherit; + color: ${({ value, error }) => + error + ? COLORS.error + : value + ? COLORS.aqua + : "var(--base-bright-gray, #e0f3ff)"}; + flex-shrink: 0; + + &:focus { + font-size: 48px; + outline: none; + } + + &::placeholder { + color: var(--base-bright-gray, #e0f3ff); + opacity: 0.5; + } +`; + +const TokenInputWrapper = styled.div` + display: flex; + min-height: 148px; + justify-content: space-between; + align-items: center; + align-self: stretch; + background: transparent; + position: relative; + padding: 24px; + border-radius: 24px; + background: ${COLORS["black-700"]}; + box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.08); +`; + +const Wrapper = styled.div` + position: relative; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: center; + gap: 8px; + align-self: stretch; +`; + +const QuickSwapButton = styled.button` + display: flex; + width: 46px; + height: 38px; + position: absolute; + left: calc(50% - 20px); + top: calc(50% - 16px); + justify-content: center; + align-items: center; + background: ${COLORS["black-700"]}; + border: 3px solid ${COLORS["black-800"]}; + border-radius: 15px; + z-index: 4; + cursor: pointer; + + & * { + flex-shrink: 0; + } + + &:hover { + svg { + color: white; + } + } +`; diff --git a/src/views/SwapAndBridge/components/QuoteWarning.tsx b/src/views/SwapAndBridge/components/QuoteWarning.tsx new file mode 100644 index 000000000..fcf120f97 --- /dev/null +++ b/src/views/SwapAndBridge/components/QuoteWarning.tsx @@ -0,0 +1,54 @@ +import styled from "@emotion/styled"; +import { COLORS } from "utils"; +import { ReactComponent as WarningTriangle } from "assets/icons/warning_triangle_filled.svg"; + +type QuoteWarningProps = { + message: string | null; +}; + +export const QuoteWarning = ({ message }: QuoteWarningProps) => { + if (!message) { + return null; + } + + return ( + + + + + {message} + + ); +}; + +const WarningContainer = styled.div` + display: flex; + align-items: flex-start; + gap: 12px; + padding: 16px; + border-radius: 16px; + background: ${COLORS["black-700"]}; + border: 1px solid ${COLORS.warning}; + width: 100%; +`; + +const AlertIcon = styled.div` + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + color: ${COLORS.warning}; + margin-top: 2px; + + svg { + color: inherit; + } +`; + +const WarningText = styled.p` + color: ${COLORS["light-200"]}; + font-size: 14px; + font-weight: 400; + line-height: 150%; + margin: 0; +`; diff --git a/src/views/SwapAndBridge/hooks/useDefaultRoute.ts b/src/views/SwapAndBridge/hooks/useDefaultRoute.ts new file mode 100644 index 000000000..902bfe79e --- /dev/null +++ b/src/views/SwapAndBridge/hooks/useDefaultRoute.ts @@ -0,0 +1,100 @@ +import { useCallback, useEffect, useMemo, useState } from "react"; +import { useConnectionEVM } from "hooks/useConnectionEVM"; +import { useEnrichedCrosschainBalances } from "hooks/useEnrichedCrosschainBalances"; +import { CHAIN_IDs } from "utils"; +import { EnrichedToken } from "../components/ChainTokenSelector/ChainTokenSelectorModal"; +import { useConnectionSVM } from "hooks/useConnectionSVM"; +import { usePrevious } from "@uidotdev/usehooks"; + +type DefaultRoute = { + inputToken: EnrichedToken | null; + outputToken: EnrichedToken | null; +}; + +export function useDefaultRoute(): DefaultRoute { + const [defaultInputToken, setDefaultInputToken] = + useState(null); + const [defaultOutputToken, setDefaultOutputToken] = + useState(null); + const [hasSetInitial, setHasSetInitial] = useState(false); + const [hasSetConnected, setHasSetConnected] = useState(false); + + const { isConnected: isConnectedEVM, chainId: chainIdEVM } = + useConnectionEVM(); + const { isConnected: isConnectedSVM, chainId: chainIdSVM } = + useConnectionSVM(); + const routeData = useEnrichedCrosschainBalances(); + + const anyConnected = isConnectedEVM || isConnectedSVM; + const previouslyConnected = usePrevious(anyConnected); + const chainId = chainIdEVM || chainIdSVM; + const hasRouteData = Object.keys(routeData).length ? true : false; + + const findUsdcToken = useCallback( + (targetChainId: number) => { + const tokensOnChain = routeData[targetChainId] || []; + return tokensOnChain.find( + (token) => token.symbol.toUpperCase() === "USDC" + ); + }, + [routeData] + ); + + // initial load + useEffect(() => { + // Wait for balances to be available + if (!hasRouteData || hasSetInitial) { + return; + } + // Wallet is not connected: Base -> Arbitrum + const inputToken = findUsdcToken(CHAIN_IDs.BASE); + const outputToken = findUsdcToken(CHAIN_IDs.ARBITRUM); + setDefaultInputToken(inputToken ?? null); + setDefaultOutputToken(outputToken ?? null); + setHasSetInitial(true); + }, [findUsdcToken, hasSetInitial, hasRouteData]); + + // connect wallet + useEffect(() => { + // Wait for balances to be available + if (!hasRouteData) { + return; + } + + // only first connection - also check hasSetConnected to prevent infinite loop + if (!previouslyConnected && anyConnected && chainId && !hasSetConnected) { + let inputToken: EnrichedToken | undefined; + let outputToken: EnrichedToken | undefined; + + if (chainId === CHAIN_IDs.ARBITRUM) { + // Special case: If on Arbitrum, use Arbitrum -> Base + inputToken = findUsdcToken(CHAIN_IDs.ARBITRUM); + outputToken = findUsdcToken(CHAIN_IDs.BASE); + } else { + // Use wallet's current network -> Arbitrum + inputToken = findUsdcToken(chainId); + outputToken = findUsdcToken(CHAIN_IDs.ARBITRUM); + } + + setDefaultInputToken(inputToken || null); + setDefaultOutputToken(outputToken || null); + setHasSetConnected(true); + } + }, [ + anyConnected, + hasRouteData, + chainId, + findUsdcToken, + previouslyConnected, + hasSetConnected, + ]); + + // Memoize the return value to prevent unnecessary re-renders + return useMemo( + () => ({ + inputToken: defaultInputToken, + outputToken: defaultOutputToken, + }), + [defaultInputToken, defaultOutputToken] + ); +} diff --git a/src/views/SwapAndBridge/hooks/useSwapAndBridge.ts b/src/views/SwapAndBridge/hooks/useSwapAndBridge.ts new file mode 100644 index 000000000..f314d2ea3 --- /dev/null +++ b/src/views/SwapAndBridge/hooks/useSwapAndBridge.ts @@ -0,0 +1,363 @@ +import { useCallback, useEffect, useMemo, useState } from "react"; +import { BigNumber } from "ethers"; + +import { AmountInputError } from "../../Bridge/utils"; +import useSwapQuote from "./useSwapQuote"; +import { EnrichedToken } from "../components/ChainTokenSelector/ChainTokenSelectorModal"; +import { + useSwapApprovalAction, + SwapApprovalData, +} from "./useSwapApprovalAction"; +import { useValidateSwapAndBridge } from "./useValidateSwapAndBridge"; +import { BridgeButtonState } from "../components/ConfirmationButton"; +import { useDebounce } from "@uidotdev/usehooks"; +import { useDefaultRoute } from "./useDefaultRoute"; +import { useHistory } from "react-router-dom"; +import { getEcosystem, getQuoteWarningMessage } from "utils"; +import { useConnectionEVM } from "hooks/useConnectionEVM"; +import { useConnectionSVM } from "hooks/useConnectionSVM"; +import { useToAccount } from "views/Bridge/hooks/useToAccount"; + +export type UseSwapAndBridgeReturn = { + inputToken: EnrichedToken | null; + outputToken: EnrichedToken | null; + setInputToken: (t: EnrichedToken | null) => void; + setOutputToken: (t: EnrichedToken | null) => void; + quickSwap: () => void; + + amount: BigNumber | null; + setAmount: (a: BigNumber | null) => void; + isAmountOrigin: boolean; + setIsAmountOrigin: (v: boolean) => void; + // route + swapQuote: ReturnType["data"]; + isQuoteLoading: boolean; + expectedInputAmount?: string; + expectedOutputAmount?: string; + destinationChainEcosystem: "svm" | "evm"; + // validation + validationError?: AmountInputError; + validationWarning?: AmountInputError; + validationErrorFormatted?: string | undefined; + + // Button state information + buttonState: BridgeButtonState; + buttonDisabled: boolean; + buttonLoading: boolean; + buttonLabel: string; + walletTypeToConnect?: "evm" | "svm"; // Which wallet type needs to be connected + + // Account management + toAccountManagement: ReturnType; + + // Legacy properties + isConnected: boolean; + isWrongNetwork: boolean; + isSubmitting: boolean; + onConfirm: () => Promise; + quoteError: Error | null; + quoteWarningMessage: string | null; +}; + +export function useSwapAndBridge(): UseSwapAndBridgeReturn { + const [inputToken, setInputToken] = useState(null); + const [outputToken, setOutputToken] = useState(null); + const [amount, setAmount] = useState(null); + const [isAmountOrigin, setIsAmountOrigin] = useState(true); + + const debouncedAmount = useDebounce(amount, 300); + const defaultRoute = useDefaultRoute(); + + const history = useHistory(); + + const { + account: accountEVM, + connect: connectEVM, + isConnected: isConnectedEVM, + } = useConnectionEVM(); + const { + account: accountSVM, + connect: connectSVM, + isConnected: isConnectedSVM, + } = useConnectionSVM(); + + const toAccountManagement = useToAccount(outputToken?.chainId); + + const originChainEcosystem = inputToken?.chainId + ? getEcosystem(inputToken?.chainId) + : "evm"; + const destinationChainEcosystem = outputToken?.chainId + ? getEcosystem(outputToken?.chainId) + : "evm"; + + const depositor = + originChainEcosystem === "evm" ? accountEVM : accountSVM?.toBase58(); + + // Check if origin wallet is connected + const isOriginConnected = + originChainEcosystem === "evm" ? isConnectedEVM : isConnectedSVM; + + // Check if destination recipient is set (appropriate wallet connected for destination ecosystem) + const isRecipientSet = + destinationChainEcosystem === "evm" + ? !!toAccountManagement.toAccountEVM + : !!toAccountManagement.toAccountSVM; + + // Determine which wallet type needs to be connected (if any) + const walletTypeToConnect: "evm" | "svm" | undefined = (() => { + if (!isOriginConnected) { + return originChainEcosystem; + } + if (!isRecipientSet) { + return destinationChainEcosystem; + } + return undefined; + })(); + + useEffect(() => { + if (defaultRoute.inputToken && defaultRoute.outputToken) { + setInputToken((prev) => { + // Only update if token is different (avoid unnecessary re-renders) + if ( + !prev || + prev.address !== defaultRoute.inputToken!.address || + prev.chainId !== defaultRoute.inputToken!.chainId + ) { + return defaultRoute.inputToken; + } + return prev; + }); + setOutputToken((prev) => { + // Only update if token is different (avoid unnecessary re-renders) + if ( + !prev || + prev.address !== defaultRoute.outputToken!.address || + prev.chainId !== defaultRoute.outputToken!.chainId + ) { + return defaultRoute.outputToken; + } + return prev; + }); + } + }, [defaultRoute]); + + const quickSwap = useCallback(() => { + setInputToken((prevInput) => { + const prevOut = outputToken; + setOutputToken(prevInput || null); + return prevOut || null; + }); + setAmount(null); + }, [outputToken]); + + const { + data: swapQuote, + isLoading: isQuoteLoading, + error: quoteError, + } = useSwapQuote({ + origin: inputToken ? inputToken : null, + destination: outputToken ? outputToken : null, + amount: debouncedAmount, + isInputAmount: isAmountOrigin, + depositor, + recipient: toAccountManagement.currentRecipientAccount, + }); + + const approvalData: SwapApprovalData | undefined = useMemo(() => { + if (!swapQuote) return undefined; + return { + approvalTxns: swapQuote.approvalTxns, + swapTx: swapQuote.swapTx as any, + }; + }, [swapQuote]); + + const approvalAction = useSwapApprovalAction( + inputToken?.chainId || 0, + approvalData + ); + + const validation = useValidateSwapAndBridge( + amount, + isAmountOrigin, + inputToken, + outputToken, + isOriginConnected, + swapQuote?.inputAmount + ); + + const expectedInputAmount = useMemo(() => { + return swapQuote?.inputAmount?.toString(); + }, [swapQuote]); + + const expectedOutputAmount = useMemo(() => { + return swapQuote?.expectedOutputAmount?.toString(); + }, [swapQuote]); + + const onConfirm = useCallback(async () => { + // If origin wallet is not connected, connect it first + if (!isOriginConnected) { + if (originChainEcosystem === "evm") { + connectEVM({ trackSection: "bridgeForm" }); + return; + } else { + connectSVM({ trackSection: "bridgeForm" }); + return; + } + } + + // If destination recipient is not set, connect the destination wallet + if (!isRecipientSet) { + if (destinationChainEcosystem === "evm") { + connectEVM({ trackSection: "bridgeForm" }); + return; + } else { + connectSVM({ trackSection: "bridgeForm" }); + return; + } + } + + // Otherwise, proceed with the transaction + const txHash = await approvalAction.buttonActionHandler(); + // Only navigate if we got a transaction hash (not empty string from wallet connection) + if (txHash) { + history.push( + `/bridge-and-swap/${txHash}?originChainId=${inputToken?.chainId}&destinationChainId=${outputToken?.chainId}&inputTokenSymbol=${inputToken?.symbol}&outputTokenSymbol=${outputToken?.symbol}&referrer=` + ); + } + }, [ + isOriginConnected, + isRecipientSet, + originChainEcosystem, + destinationChainEcosystem, + approvalAction, + connectEVM, + connectSVM, + history, + inputToken?.chainId, + inputToken?.symbol, + outputToken?.chainId, + outputToken?.symbol, + ]); + + // Button state logic + const buttonState: BridgeButtonState = useMemo(() => { + if (approvalAction.isButtonActionLoading) return "submitting"; + if (isQuoteLoading) return "loadingQuote"; + if (quoteError) return "apiError"; + if (validation.error) return "validationError"; + if (!isOriginConnected || !isRecipientSet) return "notConnected"; + return "readyToConfirm"; + }, [ + isQuoteLoading, + quoteError, + isOriginConnected, + isRecipientSet, + approvalAction.isButtonActionLoading, + validation.error, + ]); + + const buttonLoading = useMemo(() => { + return buttonState === "loadingQuote" || buttonState === "submitting"; + }, [buttonState]); + + const quoteWarningMessage = useMemo(() => { + return getQuoteWarningMessage(quoteError); + }, [quoteError]); + + const buttonLabel = useMemo(() => { + // Show validation error in button label if present + if (validation.errorFormatted && buttonState === "validationError") { + return validation.errorFormatted; + } + + // Show API error in button label if present + if (quoteWarningMessage && buttonState === "apiError") { + return quoteWarningMessage; + } + + if (buttonState === "notConnected" && walletTypeToConnect) { + // If neither wallet is connected, show generic "Connect Wallet" + if (!isConnectedEVM && !isConnectedSVM) { + return "Connect Wallet"; + } + // Otherwise, show the specific wallet type that needs to be connected + return walletTypeToConnect === "evm" + ? "Connect EVM Wallet" + : "Connect SVM Wallet"; + } + return buttonLabels[buttonState]; + }, [ + buttonState, + walletTypeToConnect, + isConnectedEVM, + isConnectedSVM, + validation.errorFormatted, + quoteWarningMessage, + ]); + + const buttonDisabled = useMemo( + () => + approvalAction.buttonDisabled || + !!validation.error || + !inputToken || + !outputToken || + !amount || + amount.lte(0), + [ + approvalAction.buttonDisabled, + validation.error, + inputToken, + outputToken, + amount, + ] + ); + + return { + inputToken, + outputToken, + setInputToken, + setOutputToken, + quickSwap, + + amount, + setAmount, + isAmountOrigin, + setIsAmountOrigin, + + swapQuote, + isQuoteLoading, + expectedInputAmount, + expectedOutputAmount, + validationErrorFormatted: validation.errorFormatted, + validationError: validation.error, + validationWarning: validation.warn, + + // Button state information + buttonState, + buttonDisabled, + buttonLoading, + buttonLabel, + walletTypeToConnect, + + // Account management + toAccountManagement, + destinationChainEcosystem, + // Legacy properties + isConnected: isOriginConnected && isRecipientSet, + isWrongNetwork: approvalAction.isWrongNetwork, + isSubmitting: approvalAction.isButtonActionLoading, + onConfirm, + quoteError, + quoteWarningMessage, + }; +} + +const buttonLabels: Record = { + notConnected: "Connect Wallet", + readyToConfirm: "Confirm Swap", + apiError: "Confirm Swap", + submitting: "Confirming...", + wrongNetwork: "Confirm Swap", + loadingQuote: "Finalizing quote...", + validationError: "Confirm Swap", +}; diff --git a/src/views/SwapAndBridge/hooks/useSwapApprovalAction/factory.ts b/src/views/SwapAndBridge/hooks/useSwapApprovalAction/factory.ts new file mode 100644 index 000000000..314f1328b --- /dev/null +++ b/src/views/SwapAndBridge/hooks/useSwapApprovalAction/factory.ts @@ -0,0 +1,35 @@ +import { useMutation } from "@tanstack/react-query"; +import { + SwapApprovalActionStrategy, + SwapApprovalData, +} from "./strategies/types"; + +export function createSwapApprovalActionHook( + strategy: SwapApprovalActionStrategy +) { + return function useSwapApprovalAction(approvalData?: SwapApprovalData) { + const isConnected = strategy.isConnected(); + const isWrongNetwork = approvalData + ? strategy.isWrongNetwork(approvalData.swapTx.chainId) + : false; + + const action = useMutation({ + mutationFn: async () => { + if (!approvalData) throw new Error("Missing approval data"); + const txHash = await strategy.execute(approvalData); + return txHash; + }, + }); + + const buttonDisabled = !approvalData || (isConnected && action.isPending); + + return { + isConnected, + isWrongNetwork, + buttonActionHandler: action.mutateAsync, + isButtonActionLoading: action.isPending, + didActionError: action.isError, + buttonDisabled, + }; + }; +} diff --git a/src/views/SwapAndBridge/hooks/useSwapApprovalAction/index.ts b/src/views/SwapAndBridge/hooks/useSwapApprovalAction/index.ts new file mode 100644 index 000000000..f861b783e --- /dev/null +++ b/src/views/SwapAndBridge/hooks/useSwapApprovalAction/index.ts @@ -0,0 +1,28 @@ +import { createSwapApprovalActionHook } from "./factory"; +import { useConnectionSVM } from "hooks/useConnectionSVM"; +import { useConnectionEVM } from "hooks/useConnectionEVM"; +import { EVMSwapApprovalActionStrategy } from "./strategies/evm"; +import { SVMSwapApprovalActionStrategy } from "./strategies/svm"; +import { getEcosystem } from "utils"; +import { SwapApprovalData } from "./strategies/types"; + +export function useSwapApprovalAction( + originChainId: number, + approvalData?: SwapApprovalData +) { + const connectionEVM = useConnectionEVM(); + const connectionSVM = useConnectionSVM(); + + const evmHook = createSwapApprovalActionHook( + new EVMSwapApprovalActionStrategy(connectionEVM) + ); + const svmHook = createSwapApprovalActionHook( + new SVMSwapApprovalActionStrategy(connectionSVM, connectionEVM) + ); + + return getEcosystem(originChainId) === "evm" + ? evmHook(approvalData) + : svmHook(approvalData); +} + +export type { SwapApprovalData } from "./strategies/types"; diff --git a/src/views/SwapAndBridge/hooks/useSwapApprovalAction/strategies/abstract.ts b/src/views/SwapAndBridge/hooks/useSwapApprovalAction/strategies/abstract.ts new file mode 100644 index 000000000..ba311c19c --- /dev/null +++ b/src/views/SwapAndBridge/hooks/useSwapApprovalAction/strategies/abstract.ts @@ -0,0 +1,20 @@ +import { useConnectionEVM } from "hooks/useConnectionEVM"; +import { SwapApprovalActionStrategy } from "./types"; + +export abstract class AbstractSwapApprovalActionStrategy + implements SwapApprovalActionStrategy +{ + constructor(readonly evmConnection: ReturnType) {} + + abstract isConnected(): boolean; + abstract isWrongNetwork(requiredChainId: number): boolean; + abstract switchNetwork(requiredChainId: number): Promise; + abstract execute(approvalData: any): Promise; + + async assertCorrectNetwork(requiredChainId: number) { + const currentChainId = this.evmConnection.chainId; + if (currentChainId !== requiredChainId) { + await this.evmConnection.setChain(requiredChainId); + } + } +} diff --git a/src/views/SwapAndBridge/hooks/useSwapApprovalAction/strategies/evm.ts b/src/views/SwapAndBridge/hooks/useSwapApprovalAction/strategies/evm.ts new file mode 100644 index 000000000..53ecaa6e7 --- /dev/null +++ b/src/views/SwapAndBridge/hooks/useSwapApprovalAction/strategies/evm.ts @@ -0,0 +1,75 @@ +import { AbstractSwapApprovalActionStrategy } from "./abstract"; +import { useConnectionEVM } from "hooks/useConnectionEVM"; +import { ApprovalTxn, SwapApprovalData, SwapTx } from "./types"; + +export class EVMSwapApprovalActionStrategy extends AbstractSwapApprovalActionStrategy { + constructor(evmConnection: ReturnType) { + super(evmConnection); + } + + private getSigner() { + const { signer } = this.evmConnection; + if (!signer) { + throw new Error("No signer available"); + } + return signer; + } + + isConnected(): boolean { + return this.evmConnection.isConnected; + } + + isWrongNetwork(requiredChainId: number): boolean { + const connectedChainId = this.evmConnection.chainId; + return connectedChainId !== requiredChainId; + } + + async switchNetwork(requiredChainId: number): Promise { + await this.evmConnection.setChain(requiredChainId); + } + + async approve(approvalData: SwapApprovalData): Promise { + const signer = this.getSigner(); + // approvals first + const approvals: ApprovalTxn[] = approvalData.approvalTxns || []; + for (const approval of approvals) { + await this.switchNetwork(approval.chainId); + await this.assertCorrectNetwork(approval.chainId); + await signer.sendTransaction({ + to: approval.to, + data: approval.data, + chainId: approval.chainId, + }); + } + return true; + } + + async swap(approvalData: SwapApprovalData): Promise { + const signer = this.getSigner(); + + const swapTx: SwapTx = approvalData.swapTx; + await this.switchNetwork(swapTx.chainId); + await this.assertCorrectNetwork(swapTx.chainId); + const tx = await signer.sendTransaction({ + to: swapTx.to, + data: swapTx.data, + value: swapTx.value, + chainId: swapTx.chainId, + gasPrice: undefined, + maxFeePerGas: swapTx.maxFeePerGas as any, + maxPriorityFeePerGas: swapTx.maxPriorityFeePerGas as any, + gasLimit: swapTx.gas as any, + }); + return tx.hash; + } + + async execute(approvalData: SwapApprovalData): Promise { + try { + await this.approve(approvalData); + return await this.swap(approvalData); + } catch (e) { + console.error(e); + throw e; + } + } +} diff --git a/src/views/SwapAndBridge/hooks/useSwapApprovalAction/strategies/svm.ts b/src/views/SwapAndBridge/hooks/useSwapApprovalAction/strategies/svm.ts new file mode 100644 index 000000000..9dca85820 --- /dev/null +++ b/src/views/SwapAndBridge/hooks/useSwapApprovalAction/strategies/svm.ts @@ -0,0 +1,47 @@ +import { AbstractSwapApprovalActionStrategy } from "./abstract"; +import { useConnectionSVM } from "hooks/useConnectionSVM"; +import { useConnectionEVM } from "hooks/useConnectionEVM"; +import { SwapApprovalData, SwapTx } from "./types"; + +export class SVMSwapApprovalActionStrategy extends AbstractSwapApprovalActionStrategy { + constructor( + private readonly svmConnection: ReturnType, + evmConnection: ReturnType + ) { + super(evmConnection); + } + + isConnected(): boolean { + return this.svmConnection.isConnected; + } + + isWrongNetwork(_: number): boolean { + return !this.svmConnection.isConnected; + } + + async switchNetwork(_: number): Promise { + await this.svmConnection.connect(); + } + + // stubbed for now + approve(_approvalData: SwapApprovalData): boolean { + return true; + } + + async swap(approvalData: SwapApprovalData): Promise { + if (!this.svmConnection.wallet?.adapter) { + throw new Error("Wallet needs to be connected"); + } + + const swapTx: SwapTx = approvalData.swapTx; + const sig = await this.svmConnection.provider.sendRawTransaction( + Buffer.from(swapTx.data, "base64") + ); + return sig; + } + + async execute(approvalData: SwapApprovalData): Promise { + this.approve(approvalData); + return this.swap(approvalData); + } +} diff --git a/src/views/SwapAndBridge/hooks/useSwapApprovalAction/strategies/types.ts b/src/views/SwapAndBridge/hooks/useSwapApprovalAction/strategies/types.ts new file mode 100644 index 000000000..d2b77ec07 --- /dev/null +++ b/src/views/SwapAndBridge/hooks/useSwapApprovalAction/strategies/types.ts @@ -0,0 +1,32 @@ +export type ApprovalTxn = { + chainId: number; + to: string; + data: string; +}; + +export type SwapTx = { + simulationSuccess: boolean; + chainId: number; + to: string; + data: string; + value?: string; + gas?: string; + maxFeePerGas?: string; + maxPriorityFeePerGas?: string; +}; + +export type SwapApprovalData = { + approvalTxns?: ApprovalTxn[]; + swapTx: SwapTx; +}; + +export type ApproveAndExecuteParams = { + approvalData: SwapApprovalData; +}; + +export type SwapApprovalActionStrategy = { + isConnected(): boolean; + isWrongNetwork(requiredChainId: number): boolean; + switchNetwork(requiredChainId: number): Promise; + execute(approvalData: SwapApprovalData): Promise; +}; diff --git a/src/views/SwapAndBridge/hooks/useSwapQuote.ts b/src/views/SwapAndBridge/hooks/useSwapQuote.ts new file mode 100644 index 000000000..8ff561892 --- /dev/null +++ b/src/views/SwapAndBridge/hooks/useSwapQuote.ts @@ -0,0 +1,101 @@ +import { useQuery } from "@tanstack/react-query"; +import { BigNumber } from "ethers"; +import { + SwapApiToken, + swapApprovalApiCall, + SwapApprovalApiCallReturnType, + SwapApprovalApiQueryParams, +} from "utils/serverless-api/prod/swap-approval"; +import { chainIsSvm } from "utils/sdk"; + +// Placeholder addresses for quote simulation when wallet is not connected +const PLACEHOLDER_EVM_ADDRESS = "0x9A8f92a830A5cB89a3816e3D267CB7791c16b04D"; +const PLACEHOLDER_SVM_ADDRESS = "FmMK62wrtWVb5SVoTZftSCGw3nEDA79hDbZNTRnC1R6t"; + +type SwapQuoteParams = { + origin: SwapApiToken | null; + destination: SwapApiToken | null; + amount: BigNumber | null; + isInputAmount: boolean; + depositor: string | undefined; + recipient: string | undefined; + integratorId?: string; + refundAddress?: string; + refundOnOrigin?: boolean; + slippageTolerance?: number; +}; + +const useSwapQuote = ({ + origin, + destination, + amount, + isInputAmount, + recipient, + integratorId, + refundAddress, + depositor, + refundOnOrigin = true, +}: SwapQuoteParams) => { + const { data, isLoading, error } = useQuery({ + queryKey: [ + "swap-quote", + origin, + destination, + amount, + isInputAmount, + depositor, + recipient, + ], + queryFn: async (): Promise => { + if (Number(amount) <= 0) { + return undefined; + } + if (!origin || !destination || !amount) { + throw new Error("Missing required swap quote parameters"); + } + + // Use appropriate placeholder address based on chain ecosystem when wallet is not connected + const getPlaceholderAddress = (chainId: number) => { + return chainIsSvm(chainId) + ? PLACEHOLDER_SVM_ADDRESS + : PLACEHOLDER_EVM_ADDRESS; + }; + + const isUsingPlaceholderDepositor = !depositor; + const effectiveDepositor = + depositor || getPlaceholderAddress(origin.chainId); + const effectiveRecipient = + recipient || getPlaceholderAddress(destination.chainId); + + const params: SwapApprovalApiQueryParams = { + tradeType: isInputAmount ? "exactInput" : "minOutput", + inputToken: origin.address, + outputToken: destination.address, + originChainId: origin.chainId, + destinationChainId: destination.chainId, + depositor: effectiveDepositor, + recipient: effectiveRecipient, + amount: amount.toString(), + refundOnOrigin, + // Skip transaction estimation when using placeholder address + skipOriginTxEstimation: isUsingPlaceholderDepositor, + ...(integratorId ? { integratorId } : {}), + ...(refundAddress ? { refundAddress } : {}), + }; + + const data = await swapApprovalApiCall(params); + return data; + }, + enabled: !!origin?.address && !!destination?.address && !!amount, + retry: 2, + + refetchInterval(query) { + // only refetch if data + return query.state.status === "success" ? 10_000 : false; + }, + }); + + return { data, isLoading, error }; +}; + +export default useSwapQuote; diff --git a/src/views/SwapAndBridge/hooks/useValidateSwapAndBridge.ts b/src/views/SwapAndBridge/hooks/useValidateSwapAndBridge.ts new file mode 100644 index 000000000..681615e21 --- /dev/null +++ b/src/views/SwapAndBridge/hooks/useValidateSwapAndBridge.ts @@ -0,0 +1,87 @@ +import { useMemo } from "react"; +import { BigNumber } from "ethers"; + +import { AmountInputError } from "../../Bridge/utils"; +import { EnrichedToken } from "../components/ChainTokenSelector/ChainTokenSelectorModal"; +import { validationErrorTextMap } from "views/Bridge/components/AmountInput"; + +export type ValidationResult = { + error?: AmountInputError; + warn?: AmountInputError; + errorFormatted?: string; +}; + +export function useValidateSwapAndBridge( + amount: BigNumber | null, + isAmountOrigin: boolean, + inputToken: EnrichedToken | null, + outputToken: EnrichedToken | null, + isConnected: boolean, + swapQuoteInputAmount: BigNumber | undefined +): ValidationResult { + const validation = useMemo(() => { + let errorType: AmountInputError | undefined = undefined; + + // Only validate if wallet is connected + if (isConnected) { + // Check if input token is selected + if (!inputToken) { + errorType = AmountInputError.NO_INPUT_TOKEN_SELECTED; + } + // Check if output token is selected + else if (!outputToken) { + errorType = AmountInputError.NO_OUTPUT_TOKEN_SELECTED; + } + // Check if amount is entered + else if (!amount || amount.isZero()) { + errorType = AmountInputError.NO_AMOUNT_ENTERED; + } + // invalid amount + else if (amount.lte(0)) { + errorType = AmountInputError.INVALID; + } + // balance check for origin-side inputs + else if (isAmountOrigin && inputToken?.balance) { + if (amount.gt(inputToken.balance)) { + errorType = AmountInputError.INSUFFICIENT_BALANCE; + } + } else if (!isAmountOrigin && swapQuoteInputAmount) { + if (swapQuoteInputAmount?.gt(inputToken.balance)) { + errorType = AmountInputError.INSUFFICIENT_BALANCE; + } + } + } + return { + error: errorType, + warn: undefined as AmountInputError | undefined, + errorFormatted: getValidationErrorText({ + validationError: errorType, + inputToken, + outputToken, + }), + }; + }, [ + isConnected, + inputToken, + outputToken, + amount, + isAmountOrigin, + swapQuoteInputAmount, + ]); + + return validation; +} + +function getValidationErrorText(props: { + validationError?: AmountInputError; + inputToken: EnrichedToken | null; + outputToken: EnrichedToken | null; +}): string | undefined { + if (!props.validationError) { + return; + } + return validationErrorTextMap[props.validationError]?.replace( + "[INPUT_TOKEN]", + props.inputToken?.symbol ?? "" + ); +} diff --git a/src/views/SwapAndBridge/index.tsx b/src/views/SwapAndBridge/index.tsx new file mode 100644 index 000000000..a77e0d9d7 --- /dev/null +++ b/src/views/SwapAndBridge/index.tsx @@ -0,0 +1,78 @@ +import { LayoutV2 } from "components"; +import styled from "@emotion/styled"; +import { InputForm } from "./components/InputForm"; +import { ConfirmationButton } from "./components/ConfirmationButton"; +import { useSwapAndBridge } from "./hooks/useSwapAndBridge"; + +export default function SwapAndBridge() { + const { + inputToken, + outputToken, + setInputToken, + setOutputToken, + amount, + setAmount, + isAmountOrigin, + setIsAmountOrigin, + swapQuote, + isQuoteLoading, + expectedInputAmount, + expectedOutputAmount, + validationError, + buttonState, + buttonDisabled, + buttonLoading, + buttonLabel, + onConfirm, + destinationChainEcosystem, + toAccountManagement, + } = useSwapAndBridge(); + + return ( + + + + + + + ); +} + +const Wrapper = styled.div` + display: flex; + flex-direction: column; + + gap: 8px; + + align-items: center; + justify-content: center; + + width: 100%; + + padding-top: 64px; +`; diff --git a/vercel.json b/vercel.json index 419e5daf2..20670dadd 100644 --- a/vercel.json +++ b/vercel.json @@ -59,6 +59,16 @@ "source": "/about", "destination": "https://across.to", "permanent": true + }, + { + "source": "/bridge", + "destination": "/bridge-and-swap", + "permanent": false + }, + { + "source": "/bridge/:txHash", + "destination": "/bridge-and-swap/:txHash", + "permanent": false } ], "headers": [ diff --git a/yarn.lock b/yarn.lock index 7823250c2..1690ab285 100644 --- a/yarn.lock +++ b/yarn.lock @@ -66,10 +66,10 @@ "@openzeppelin/contracts" "4.1.0" "@uma/core" "^2.18.0" -"@across-protocol/contracts@^4.1.11": - version "4.1.11" - resolved "https://registry.yarnpkg.com/@across-protocol/contracts/-/contracts-4.1.11.tgz#6194ca1d3a78edbbbcd6a047f2ade9bbc911e536" - integrity sha512-ErLVNzMgF9H7XkMRtI4fQQ4/IVaO4GAj/FShUxqSHLspcEGreeeyxRj5hfPsALOPQdGvMiT1iJmx7I0oVi1P4w== +"@across-protocol/contracts@^4.1.12": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@across-protocol/contracts/-/contracts-4.1.12.tgz#dbf0d4f105884f2cd5a25280f0aac635b8505a5c" + integrity sha512-+d1xTLBxGNHDMuZDMaZPunDb46SYzAsIfqrwK6252cP0+9dG7XFX+6hBXpeqyytp7ESe+W8UgpGQdSCxXAdhkw== dependencies: "@across-protocol/constants" "^3.1.77" "@coral-xyz/anchor" "^0.31.1" @@ -10451,6 +10451,11 @@ "@typescript-eslint/types" "7.13.1" eslint-visitor-keys "^3.4.3" +"@uidotdev/usehooks@^2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@uidotdev/usehooks/-/usehooks-2.4.1.tgz#4b733eaeae09a7be143c6c9ca158b56cc1ea75bf" + integrity sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg== + "@uma/common@^2.17.0", "@uma/common@^2.37.3": version "2.37.3" resolved "https://registry.yarnpkg.com/@uma/common/-/common-2.37.3.tgz#0d7fda1227e3a05563544bb36f418a790c81129d" @@ -23183,6 +23188,11 @@ react-focus-lock@^2.5.2: use-callback-ref "^1.2.5" use-sidecar "^1.0.5" +react-hotkeys-hook@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/react-hotkeys-hook/-/react-hotkeys-hook-5.1.0.tgz#794eaa4428363b2312e26b19d49301fb05052e24" + integrity sha512-GCNGXjBzV9buOS3REoQFmSmE4WTvBhYQ0YrAeeMZI83bhXg3dRWsLHXDutcVDdEjwJqJCxk5iewWYX5LtFUd7g== + react-inspector@^6.0.0: version "6.0.2" resolved "https://registry.yarnpkg.com/react-inspector/-/react-inspector-6.0.2.tgz#aa3028803550cb6dbd7344816d5c80bf39d07e9d"