Commit e3ff4948 authored by isstuev's avatar isstuev

native token icon separate

parent aff6f7ca
...@@ -4,7 +4,7 @@ export const base = { ...@@ -4,7 +4,7 @@ export const base = {
average_block_time: 6212.0, average_block_time: 6212.0,
coin_price: '0.00199678', coin_price: '0.00199678',
coin_price_change_percentage: -7.42, coin_price_change_percentage: -7.42,
coin_icon: '', coin_image: 'http://localhost:3100/utia.jpg',
gas_prices: { gas_prices: {
average: { average: {
fiat_price: '1.39', fiat_price: '1.39',
......
[{
"title": "Ethereum",
"url": "https://eth.blockscout.com/",
"group": "Mainnets",
"isActive": true,
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/ethereum.svg"
},
{
"title": "Optimism",
"url": "https://optimism.blockscout.com/",
"group": "Mainnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/optimism.svg"
},
{
"title": "Base Chain",
"url": "https://base.blockscout.com/",
"group": "Mainnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/base.svg"
},
{
"title": "RSK",
"url": "https://blockscout.com/rsk/mainnet",
"group": "Mainnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/rsk.svg"
},
{
"title": "LightLink Phoenix",
"url": "https://phoenix.lightlink.blockscout.com/",
"group": "Mainnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/lightlink-short.svg"
},
{
"title": "Neon",
"url": "https://neon.blockscout.com/",
"group": "Mainnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/neon-short.svg"
},
{
"title": "Ethereum Classic",
"url": "https://blockscout.com/etc/mainnet",
"group": "Mainnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/ethereum-classic.svg"
},
{
"title": "Gnosis Chain",
"url": "https://gnosis.blockscout.com/",
"group": "Mainnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/gnosis.svg"
},
{
"title": "Astar (EVM)",
"url": "https://blockscout.com/astar",
"group": "Mainnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/astar.svg"
},
{
"title": "Shiden (EVM)",
"url": "https://blockscout.com/shiden",
"group": "Mainnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/shiden.svg"
},
{
"title": "Goerli",
"url": "https://eth-goerli.blockscout.com/",
"group": "Testnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/goerli.svg",
"invertIconInDarkMode": true
},
{
"title": "Sepolia",
"url": "https://eth-sepolia.blockscout.com/",
"group": "Testnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/sepolia.png"
},
{
"title": "Holesky",
"url": "https://eth-holesky.blockscout.com/",
"group": "Testnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/ethereum.svg"
},
{
"title": "Base Göerli",
"url": "https://base-goerli.blockscout.com/",
"group": "Testnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/base.svg",
"invertIconInDarkMode": true
},
{
"title": "Base Sepolia",
"url": "https://base-sepolia.blockscout.com/",
"group": "Testnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/base.svg",
"invertIconInDarkMode": true
},
{
"title": "Optimism Goerli",
"url": "https://optimism-goerli.blockscout.com/",
"group": "Testnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/optimism.svg"
},
{
"title": "Optimism Sepolia",
"url": "https://optimism-sepolia.blockscout.com/",
"group": "Testnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/optimism.svg"
},
{
"title": "Optimism Bedrock Beta",
"url": "https://blockscout.com/optimism/bedrock-beta",
"group": "Testnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/optimism.svg"
},
{
"title": "ZetaChain testnet",
"url": "https://zetachain-athens-3.blockscout.com/",
"group": "Testnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/zetachain.svg",
"invertIconInDarkMode": true
},
{
"title": "LightLink Pegasus",
"url": "https://pegasus.lightlink.blockscout.com/",
"group": "Testnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/lightlink-short.svg",
"invertIconInDarkMode": true
},
{
"title": "Neon Devnet",
"url": "https://neon-devnet.blockscout.com/",
"group": "Testnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/neon-short.svg"
},
{
"title": "Gnosis Chiado",
"url": "https://gnosis-chiado.blockscout.com/",
"group": "Testnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/gnosis_chiado.svg"
},
{
"title": "Shibuya (EVM)",
"url": "https://blockscout.com/shibuya",
"group": "Testnets",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/shibuya.svg",
"invertIconInDarkMode": true
},
{
"title": "Optimism Opcraft",
"url": "https://blockscout.com/optimism/opcraft",
"group": "Other",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/optimism_opcraft.svg"
},
{
"title": "ARTIS-Σ1",
"url": "https://blockscout.com/artis/sigma1",
"group": "Other",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/artis.svg"
},
{
"title": "LUKSO L14",
"url": "https://blockscout.com/lukso/l14",
"group": "Other",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/lukso.svg"
},
{
"title": "POA",
"url": "https://blockscout.com/poa/core",
"group": "Other",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/poa.svg"
},
{
"title": "POA Sokol",
"url": "https://blockscout.com/poa/sokol",
"group": "Other",
"icon": "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/poa-sokol.svg"
}
]
[
{
"title": "Partners",
"links": [
{
"text": "MetaSuites",
"url": "https://blocksec.com/metasuites"
},
{
"text": "Sourcify",
"url": "https://sourcify.dev/"
},
{
"text": "DRPC",
"url": "https://drpc.org?ref=559183"
},
{
"text": "BlockSec",
"url": "https://blocksec.com/"
}
]
}
]
[
"Swaps",
"Bridges",
"Liquid Staking",
"Liquid staking",
"Lending",
"Yield Aggregators",
"Yield aggregators",
"CDP",
"CDPs",
"NFT",
"NFTs",
"Wallets",
"Games",
"Dev tooling",
"Dev toolings",
"Data & Analytics",
"Infra & Dev tooling",
"DeFi",
"Data",
"Bridge",
"Payments",
"Faucet",
"DAO",
"Wallet"
]
[
{
"author": "Hop",
"id": "hop-exchange",
"title": "Hop",
"logo": "https://blockscout-content.s3.amazonaws.com/hop.png",
"categories": ["Bridge"],
"shortDescription": "Hop is a scalable rollup-to-rollup general token bridge. It allows users to send tokens from one rollup or sidechain to another almost immediately without having to wait for the networks challenge period.",
"site": "https://help.hop.exchange/hc/en-us/articles/4405172445197-What-is-Hop-Protocol-",
"description": "Hop is a scalable rollup-to-rollup general token bridge. It allows users to send tokens from one rollup or sidechain to another almost immediately without having to wait for the networks challenge period.",
"external": true,
"url": "https://goerli.hop.exchange/send?token=ETH&sourceNetwork=ethereum",
"internalWallet": false
},
{
"author": "Blockscout",
"id": "token-approval-tracker",
"title": "Token Approval Tracker",
"logo": "https://blockscout-content.s3.amazonaws.com/token-approval.png",
"categories": ["Infra & Dev tooling"],
"shortDescription": "Token Approval Tracker shows all approvals for any ERC20-compliant tokens and NFTs and lets to revoke them or adjust the approved amount.",
"site": "https://docs.blockscout.com/for-users/blockscout-apps/token-approval-tracker",
"description": "Token Approval Tracker shows all approvals for any ERC20-compliant tokens and NFTs and lets to revoke them or adjust the approved amount.",
"external": false,
"url": "https://approval-tracker.apps.blockscout.com/",
"internalWallet": false,
"priority": 0
},
{
"author": "Revoke",
"id": "revoke.cash",
"title": "Revoke.cash",
"logo": "https://blockscout-content.s3.amazonaws.com/revokecash.png",
"categories": ["Infra & Dev tooling"],
"shortDescription": "Revoke.cash comes in as a preventative tool to manage your token allowances and practice proper wallet hygiene. By regularly revoking active allowances you reduce the chances of becoming the victim of allowance exploits.",
"site": "https://revoke.cash/about",
"external": false,
"description": "Revoke.cash comes in as a preventative tool to manage your token allowances and practice proper wallet hygiene. By regularly revoking active allowances you reduce the chances of becoming the victim of allowance exploits.",
"url": "https://revoke.cash/",
"internalWallet": true,
"priority": 2
},
{
"author": "Aave",
"id": "aave",
"title": "Aave",
"logo": "https://blockscout-content.s3.amazonaws.com/aave.png",
"categories": ["DeFi"],
"shortDescription": "Aave is a decentralised non-custodial liquidity market protocol where users can participate as suppliers or borrowers. Suppliers provide liquidity to the market to earn a passive income, while borrowers are able to borrow in an overcollateralised (perpetually) or undercollateralised (one-block liquidity) fashion.",
"site": "https://docs.aave.com/faq/",
"external": false,
"description": "Aave is a decentralised non-custodial liquidity market protocol where users can participate as suppliers or borrowers. Suppliers provide liquidity to the market to earn a passive income, while borrowers are able to borrow in an overcollateralised (perpetually) or undercollateralised (one-block liquidity) fashion.",
"url": "https://staging.aave.com/",
"internalWallet": true,
"priority": 4
},
{
"author": "LooksRare",
"id": "looksrare",
"title": "LooksRare",
"logo": "https://blockscout-content.s3.amazonaws.com/looksrare.png",
"categories": ["NFT"],
"shortDescription": "LooksRare is the web3 NFT Marketplace where traders and collectors have earned over $1.3 Billion in rewards.",
"external": true,
"site": "https://docs.looksrare.org/about/welcome-to-looksrare",
"description": "LooksRare is the web3 NFT Marketplace where traders and collectors have earned over $1.3 Billion in rewards.",
"url": "https://goerli.looksrare.org/",
"internalWallet": false
},
{
"author": "dYdX",
"id": "dydx",
"title": "dYdX",
"logo": "https://blockscout-content.s3.amazonaws.com/dydx.png",
"categories": ["DeFi"],
"external": true,
"shortDescription": "dYdX is a leading decentralized exchange that currently supports perpetual trading. dYdX runs on smart contracts on the Ethereum blockchain, and allows users to trade with no intermediaries.",
"site": "https://help.dydx.exchange/en/articles/3047379-introduction-and-overview",
"description": "dYdX is a leading decentralized exchange that currently supports perpetual trading. dYdX runs on smart contracts on the Ethereum blockchain, and allows users to trade with no intermediaries.",
"url": "https://trade.stage.dydx.exchange/portfolio/overview",
"internalWallet": false
},
{
"author": "MetalSwap",
"id": "metalswap",
"title": "MetalSwap",
"logo": "https://blockscout-content.s3.amazonaws.com/MetalSwap.png",
"categories": ["DeFi"],
"shortDescription": "MetalSwap is a decentralised platform that enables hedging swaps in financial markets with the aim of providing a hedge for commodity traders and an investment opportunity for those who contribute to the shared liquidity of the project.",
"site": "https://docs.metalswap.finance/",
"external": false,
"description": "MetalSwap is a decentralised platform that enables hedging swaps in financial markets with the aim of providing a hedge for commodity traders and an investment opportunity for those who contribute to the shared liquidity of the project.",
"url": "https://demo.metalswap.finance/",
"internalWallet": false
},
{
"author": "FaucetDao",
"id": "faucetdao",
"title": "FaucetDao",
"logo": "https://blockscout-content.s3.amazonaws.com/faucet-dao.png",
"categories": ["Faucet"],
"shortDescription": "FaucetDao is a decentralised community fund providing liquidity and support to early-stage well-vetted blockchain projects.",
"site": "https://linktr.ee/faucet_dao",
"external": false,
"description": "FaucetDao is a decentralised community fund providing liquidity and support to early-stage well-vetted blockchain projects.",
"url": "https://www.faucetdao.shop/swap?chain=goerli",
"internalWallet": true,
"priority": 1
},
{
"author": "Uniswap",
"id": "uniswap",
"title": "Uniswap",
"logo": "https://blockscout-content.s3.amazonaws.com/uniswap.png",
"categories": ["Bridge"],
"shortDescription": "Uniswap is a cryptocurrency exchange that uses a decentralized network protocol.",
"site": "https://docs.uniswap.org/",
"external": false,
"description": "Uniswap is a cryptocurrency exchange that uses a decentralized network protocol.",
"url": "https://app.uniswap.org/swap",
"internalWallet": true,
"priority": 5
},
{
"author": "zkBob",
"id": "zkbob-wallet",
"title": "zkBob Wallet",
"logo": "https://blockscout-content.s3.amazonaws.com/zkbob-logo.png",
"categories": ["Wallet"],
"shortDescription": "A Web3 smart-contract privacy wallet based on ZKP technology. zkBob could be used for regular transfers, payments, and much more. Compliance features backed in!",
"site": "https://zkbob.com",
"description": "zkBob simplifies secure, limited-value, and anonymous token transfers for everyday users. The application accepts WETH, ETH, USDC. Once one of the tokens is deposited in the zkBob app, pool participants can transfer tokens amongst themselves in a private, secure manner. The shielded zkBob pool uses zkproofs to limit public data exposure",
"external": false,
"url": "https://staging--zkbob.netlify.app/transfer",
"twitter": "https://twitter.com/zkBob_",
"telegram": "https://t.me/zkbobcommunity",
"internalWallet": false
},
{
"author": "Swapr",
"id": "swapr",
"title": "Swapr",
"logo": "https://blockscout-content.s3.amazonaws.com/swapr.png",
"categories": ["DeFi"],
"shortDescription": "A governance-enabled automated market maker with adjustable fees.",
"site": "https://swapr.eth.dev.lastmilelabs.systems",
"description": "A governance-enabled automated market maker with adjustable fees.",
"external": false,
"url": "https://swapr.eth.limo/#/swap",
"internalWallet": false,
"priority": 3
}
]
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
window.__envs = {
NEXT_PUBLIC_HAS_BEACON_CHAIN: "true",
NEXT_PUBLIC_GIT_TAG: "v1.30.0-alpha",
NEXT_PUBLIC_GRAPHIQL_TRANSACTION: "0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d",
NEXT_PUBLIC_HOMEPAGE_CHARTS: "['daily_txs','coin_price','market_cap']",
NEXT_PUBLIC_FEATURED_NETWORKS: "https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/eth.json",
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST: "https://admin-rs.services.blockscout.com",
NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES: "[{'name':'OpenSea','collection_url':'https://opensea.io/assets/ethereum/{hash}','instance_url':'https://opensea.io/assets/ethereum/{hash}/{id}','logo_url':'https://opensea.io/static/images/logos/opensea-logo.svg'},{'name':'LooksRare','collection_url':'https://looksrare.org/collections/{hash}','instance_url':'https://looksrare.org/collections/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/looks-rare.png'}]",
NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE: "validation",
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER: "blockscout",
NEXT_PUBLIC_METADATA_SERVICE_API_HOST: "https://metadata.services.blockscout.com",
NEXT_PUBLIC_API_HOST: "eth.blockscout.com",
NEXT_PUBLIC_NETWORK_EXPLORERS: "[{'title':'Etherscan','logo':'https://github.com/blockscout/frontend-configs/blob/main/configs/explorer-logos/etherscan.png?raw=true','baseUrl':'https://etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}},{'title':'Blockchair','logo':'https://github.com/blockscout/frontend-configs/blob/main/configs/explorer-logos/blockchair.png?raw=true','baseUrl':'https://blockchair.com/','paths':{'tx':'/ethereum/transaction','address':'/ethereum/address','token':'/ethereum/erc-20/token','block':'/ethereum/block'}},{'title':'Sentio','logo':'https://github.com/blockscout/frontend-configs/blob/main/configs/explorer-logos/sentio.png?raw=true','baseUrl':'https://app.sentio.xyz/','paths':{'tx':'/tx/1','address':'/contract/1'}},{'title':'Tenderly','logo':'https://github.com/blockscout/frontend-configs/blob/main/configs/explorer-logos/tenderly.png?raw=true','baseUrl':'https://dashboard.tenderly.co','paths':{'tx':'/tx/mainnet'}},{'title':'0xPPL','logo':'https://github.com/blockscout/frontend-configs/blob/main/configs/explorer-logos/0xPPl.png?raw=true','baseUrl':'https://0xppl.com','paths':{'tx':'/Ethereum/tx','address':'/','token':'/c/Ethereum'}},{'title':'3xpl','logo':'https://github.com/blockscout/frontend-configs/blob/main/configs/explorer-logos/3xpl.png?raw=true','baseUrl':'https://3xpl.com/','paths':{'tx':'/ethereum/transaction','address':'/ethereum/address'}}]",
NEXT_PUBLIC_NETWORK_ID: "1",
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL: "ETH",
NEXT_PUBLIC_GIT_COMMIT_SHA: "2ad868770",
NEXT_PUBLIC_VISUALIZE_API_HOST: "https://visualizer.services.blockscout.com",
NEXT_PUBLIC_MARKETPLACE_ENABLED: "true",
NEXT_PUBLIC_SAFE_TX_SERVICE_URL: "https://safe-transaction-mainnet.safe.global",
NEXT_PUBLIC_CONTRACT_INFO_API_HOST: "https://contracts-info.services.blockscout.com",
NEXT_PUBLIC_APP_HOST: "localhost",
NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL: "https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json",
NEXT_PUBLIC_OG_IMAGE_URL: "https://github.com/blockscout/frontend-configs/blob/main/configs/og-images/eth.jpg?raw=true",
NEXT_PUBLIC_NETWORK_RPC_URL: "https://eth.llamarpc.com",
NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED: "true",
NEXT_PUBLIC_APP_PORT: "3000",
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS: "18",
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED: "true",
NEXT_PUBLIC_NETWORK_NAME: "Ethereum",
NEXT_PUBLIC_NETWORK_SHORT_NAME: "ETH",
NEXT_PUBLIC_APP_ENV: "development",
NEXT_PUBLIC_API_BASE_PATH: "/",
NEXT_PUBLIC_AUTH_URL: "http://localhost:3000/login",
NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM: "https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form",
NEXT_PUBLIC_NAME_SERVICE_API_HOST: "https://bens.services.blockscout.com",
NEXT_PUBLIC_APP_PROTOCOL: "http",
NEXT_PUBLIC_SEO_ENHANCED_DATA_ENABLED: "true",
NEXT_PUBLIC_LOGOUT_URL: "https://blockscoutcom.us.auth0.com/v2/logout",
NEXT_PUBLIC_AD_BANNER_PROVIDER: "hype",
NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED: "true",
NEXT_PUBLIC_STATS_API_HOST: "https://stats-eth-main.k8s-prod-1.blockscout.com",
NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM: "https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL",
NEXT_PUBLIC_NETWORK_CURRENCY_NAME: "Ether",
}
...@@ -5,14 +5,13 @@ import type { SocketMessage } from 'lib/socket/types'; ...@@ -5,14 +5,13 @@ import type { SocketMessage } from 'lib/socket/types';
import type { Address } from 'types/api/address'; import type { Address } from 'types/api/address';
import config from 'configs/app'; import config from 'configs/app';
import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery'; import { getResourceKey } from 'lib/api/useApiQuery';
import useSocketChannel from 'lib/socket/useSocketChannel'; import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage'; import useSocketMessage from 'lib/socket/useSocketMessage';
import { currencyUnits } from 'lib/units'; import { currencyUnits } from 'lib/units';
import { HOMEPAGE_STATS } from 'stubs/stats';
import CurrencyValue from 'ui/shared/CurrencyValue'; import CurrencyValue from 'ui/shared/CurrencyValue';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem'; import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import { NativeIcon } from 'ui/shared/entities/token/TokenEntity'; import NativeTokenIcon from 'ui/shared/NativeTokenIcon';
interface Props { interface Props {
data: Pick<Address, 'block_number_balance_updated_at' | 'coin_balance' | 'hash' | 'exchange_rate'>; data: Pick<Address, 'block_number_balance_updated_at' | 'coin_balance' | 'hash' | 'exchange_rate'>;
...@@ -23,13 +22,6 @@ const AddressBalance = ({ data, isLoading }: Props) => { ...@@ -23,13 +22,6 @@ const AddressBalance = ({ data, isLoading }: Props) => {
const [ lastBlockNumber, setLastBlockNumber ] = React.useState<number>(data.block_number_balance_updated_at || 0); const [ lastBlockNumber, setLastBlockNumber ] = React.useState<number>(data.block_number_balance_updated_at || 0);
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const statsQueryResult = useApiQuery('stats', {
queryOptions: {
refetchOnMount: false,
placeholderData: HOMEPAGE_STATS,
},
});
const updateData = React.useCallback((balance: string, exchangeRate: string, blockNumber: number) => { const updateData = React.useCallback((balance: string, exchangeRate: string, blockNumber: number) => {
if (blockNumber < lastBlockNumber) { if (blockNumber < lastBlockNumber) {
return; return;
...@@ -81,7 +73,7 @@ const AddressBalance = ({ data, isLoading }: Props) => { ...@@ -81,7 +73,7 @@ const AddressBalance = ({ data, isLoading }: Props) => {
alignSelf="center" alignSelf="center"
isLoading={ isLoading } isLoading={ isLoading }
> >
<NativeIcon src={ statsQueryResult.data?.coin_image } boxSize={ 6 } isLoading={ isLoading }/> <NativeTokenIcon boxSize={ 6 } mr={ 2 } isLoading={ isLoading }/>
<CurrencyValue <CurrencyValue
value={ data.coin_balance || '0' } value={ data.coin_balance || '0' }
exchangeRate={ data.exchange_rate } exchangeRate={ data.exchange_rate }
......
...@@ -14,7 +14,7 @@ interface Props { ...@@ -14,7 +14,7 @@ interface Props {
title: string; title: string;
value: (stats: HomeStats) => string; value: (stats: HomeStats) => string;
valueDiff?: (stats?: HomeStats) => number | null | undefined; valueDiff?: (stats?: HomeStats) => number | null | undefined;
icon: (stats?: { data?: HomeStats; isLoading: boolean }) => React.ReactNode; icon: React.ReactNode;
isSelected: boolean; isSelected: boolean;
onClick: (id: ChainIndicatorId) => void; onClick: (id: ChainIndicatorId) => void;
stats: UseQueryResult<HomeStats, ResourceError<unknown>>; stats: UseQueryResult<HomeStats, ResourceError<unknown>>;
...@@ -92,7 +92,7 @@ const ChainIndicatorItem = ({ id, title, value, valueDiff, icon, isSelected, onC ...@@ -92,7 +92,7 @@ const ChainIndicatorItem = ({ id, title, value, valueDiff, icon, isSelected, onC
zIndex: 1, zIndex: 1,
}} }}
> >
{ icon({ data: stats.data, isLoading: stats.isPlaceholderData }) } { icon }
<Box> <Box>
<Text fontFamily="heading" fontWeight={ 500 }>{ title }</Text> <Text fontFamily="heading" fontWeight={ 500 }>{ title }</Text>
<Flex alignItems="center"> <Flex alignItems="center">
......
...@@ -11,7 +11,7 @@ export interface TChainIndicator<R extends ChartsResources> { ...@@ -11,7 +11,7 @@ export interface TChainIndicator<R extends ChartsResources> {
title: string; title: string;
value: (stats: HomeStats) => string; value: (stats: HomeStats) => string;
valueDiff?: (stats?: HomeStats) => number | null | undefined; valueDiff?: (stats?: HomeStats) => number | null | undefined;
icon: (stats?: { data?: HomeStats; isLoading: boolean }) => React.ReactNode; icon: React.ReactNode;
hint?: string; hint?: string;
api: { api: {
resourceName: R; resourceName: R;
......
import React from 'react'; import React from 'react';
import type { TChainIndicator } from '../types'; import type { TChainIndicator } from '../types';
import type { HomeStats } from 'types/api/stats';
import type { TimeChartItem, TimeChartItemRaw } from 'ui/shared/chart/types'; import type { TimeChartItem, TimeChartItemRaw } from 'ui/shared/chart/types';
import config from 'configs/app'; import config from 'configs/app';
import { sortByDateDesc } from 'ui/shared/chart/utils/sorts'; import { sortByDateDesc } from 'ui/shared/chart/utils/sorts';
import { NativeIcon } from 'ui/shared/entities/token/TokenEntity';
import IconSvg from 'ui/shared/IconSvg'; import IconSvg from 'ui/shared/IconSvg';
import NativeTokenIcon from 'ui/shared/NativeTokenIcon';
const nonNullTailReducer = (result: Array<TimeChartItemRaw>, item: TimeChartItemRaw) => { const nonNullTailReducer = (result: Array<TimeChartItemRaw>, item: TimeChartItemRaw) => {
if (item.value === null && result.length === 0) { if (item.value === null && result.length === 0) {
...@@ -25,7 +24,7 @@ const dailyTxsIndicator: TChainIndicator<'stats_charts_txs'> = { ...@@ -25,7 +24,7 @@ const dailyTxsIndicator: TChainIndicator<'stats_charts_txs'> = {
value: (stats) => stats.transactions_today === null ? value: (stats) => stats.transactions_today === null ?
'N/A' : 'N/A' :
Number(stats.transactions_today).toLocaleString(undefined, { maximumFractionDigits: 2, notation: 'compact' }), Number(stats.transactions_today).toLocaleString(undefined, { maximumFractionDigits: 2, notation: 'compact' }),
icon: () => <IconSvg name="transactions" boxSize={ 6 } bgColor="#56ACD1" borderRadius="base" color="white"/>, icon: <IconSvg name="transactions" boxSize={ 6 } bgColor="#56ACD1" borderRadius="base" color="white"/>,
hint: `Number of transactions yesterday (0:00 - 23:59 UTC). The chart displays daily transactions for the past 30 days.`, hint: `Number of transactions yesterday (0:00 - 23:59 UTC). The chart displays daily transactions for the past 30 days.`,
api: { api: {
resourceName: 'stats_charts_txs', resourceName: 'stats_charts_txs',
...@@ -48,8 +47,7 @@ const coinPriceIndicator: TChainIndicator<'stats_charts_market'> = { ...@@ -48,8 +47,7 @@ const coinPriceIndicator: TChainIndicator<'stats_charts_market'> = {
'$N/A' : '$N/A' :
'$' + Number(stats.coin_price).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 6 }), '$' + Number(stats.coin_price).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 6 }),
valueDiff: (stats) => stats?.coin_price !== null ? stats?.coin_price_change_percentage : null, valueDiff: (stats) => stats?.coin_price !== null ? stats?.coin_price_change_percentage : null,
icon: (stats?: { data?: HomeStats; isLoading: boolean }) => icon: <NativeTokenIcon boxSize={ 6 }/>,
<NativeIcon src={ stats?.data?.coin_image } boxSize={ 6 } marginRight={ 0 } isLoading={ stats?.isLoading }/>,
hint: `${ config.chain.currency.symbol } token daily price in USD.`, hint: `${ config.chain.currency.symbol } token daily price in USD.`,
api: { api: {
resourceName: 'stats_charts_market', resourceName: 'stats_charts_market',
...@@ -72,7 +70,7 @@ const secondaryCoinPriceIndicator: TChainIndicator<'stats_charts_secondary_coin_ ...@@ -72,7 +70,7 @@ const secondaryCoinPriceIndicator: TChainIndicator<'stats_charts_secondary_coin_
'$N/A' : '$N/A' :
'$' + Number(stats.secondary_coin_price).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 6 }), '$' + Number(stats.secondary_coin_price).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 6 }),
valueDiff: () => null, valueDiff: () => null,
icon: () => <NativeIcon boxSize={ 6 } marginRight={ 0 }/>, icon: <NativeTokenIcon boxSize={ 6 }/>,
hint: `${ config.chain.secondaryCoin.symbol } token daily price in USD.`, hint: `${ config.chain.secondaryCoin.symbol } token daily price in USD.`,
api: { api: {
resourceName: 'stats_charts_secondary_coin_price', resourceName: 'stats_charts_secondary_coin_price',
...@@ -94,7 +92,7 @@ const marketPriceIndicator: TChainIndicator<'stats_charts_market'> = { ...@@ -94,7 +92,7 @@ const marketPriceIndicator: TChainIndicator<'stats_charts_market'> = {
value: (stats) => stats.market_cap === null ? value: (stats) => stats.market_cap === null ?
'$N/A' : '$N/A' :
'$' + Number(stats.market_cap).toLocaleString(undefined, { maximumFractionDigits: 2, notation: 'compact' }), '$' + Number(stats.market_cap).toLocaleString(undefined, { maximumFractionDigits: 2, notation: 'compact' }),
icon: () => <IconSvg name="globe" boxSize={ 6 } bgColor="#6A5DCC" borderRadius="base" color="white"/>, icon: <IconSvg name="globe" boxSize={ 6 } bgColor="#6A5DCC" borderRadius="base" color="white"/>,
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
hint: 'The total market value of a cryptocurrency\'s circulating supply. It is analogous to the free-float capitalization in the stock market. Market Cap = Current Price x Circulating Supply.', hint: 'The total market value of a cryptocurrency\'s circulating supply. It is analogous to the free-float capitalization in the stock market. Market Cap = Current Price x Circulating Supply.',
api: { api: {
...@@ -131,7 +129,7 @@ const tvlIndicator: TChainIndicator<'stats_charts_market'> = { ...@@ -131,7 +129,7 @@ const tvlIndicator: TChainIndicator<'stats_charts_market'> = {
value: (stats) => stats.tvl === null ? value: (stats) => stats.tvl === null ?
'$N/A' : '$N/A' :
'$' + Number(stats.tvl).toLocaleString(undefined, { maximumFractionDigits: 2, notation: 'compact' }), '$' + Number(stats.tvl).toLocaleString(undefined, { maximumFractionDigits: 2, notation: 'compact' }),
icon: () => <IconSvg name="lock" boxSize={ 6 } bgColor="#517FDB" borderRadius="base" color="white"/>, icon: <IconSvg name="lock" boxSize={ 6 } bgColor="#517FDB" borderRadius="base" color="white"/>,
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
hint: 'Total value of digital assets locked or staked in a chain', hint: 'Total value of digital assets locked or staked in a chain',
api: { api: {
......
...@@ -8,8 +8,8 @@ import { HOMEPAGE_STATS } from 'stubs/stats'; ...@@ -8,8 +8,8 @@ import { HOMEPAGE_STATS } from 'stubs/stats';
import GasTrackerChart from 'ui/gasTracker/GasTrackerChart'; import GasTrackerChart from 'ui/gasTracker/GasTrackerChart';
import GasTrackerNetworkUtilization from 'ui/gasTracker/GasTrackerNetworkUtilization'; import GasTrackerNetworkUtilization from 'ui/gasTracker/GasTrackerNetworkUtilization';
import GasTrackerPrices from 'ui/gasTracker/GasTrackerPrices'; import GasTrackerPrices from 'ui/gasTracker/GasTrackerPrices';
import { NativeIcon } from 'ui/shared/entities/token/TokenEntity';
import GasInfoUpdateTimer from 'ui/shared/gas/GasInfoUpdateTimer'; import GasInfoUpdateTimer from 'ui/shared/gas/GasInfoUpdateTimer';
import NativeTokenIcon from 'ui/shared/NativeTokenIcon';
import PageTitle from 'ui/shared/Page/PageTitle'; import PageTitle from 'ui/shared/Page/PageTitle';
const GasTracker = () => { const GasTracker = () => {
...@@ -56,7 +56,7 @@ const GasTracker = () => { ...@@ -56,7 +56,7 @@ const GasTracker = () => {
) } ) }
{ data?.coin_price && ( { data?.coin_price && (
<Skeleton isLoaded={ !isLoading } ml={{ base: 0, lg: 'auto' }} whiteSpace="pre" display="flex" alignItems="center"> <Skeleton isLoaded={ !isLoading } ml={{ base: 0, lg: 'auto' }} whiteSpace="pre" display="flex" alignItems="center">
<NativeIcon src={ data?.coin_image } boxSize={ 6 }/> <NativeTokenIcon mr={ 2 } boxSize={ 6 }/>
<chakra.span color="text_secondary">{ config.chain.currency.symbol }</chakra.span> <chakra.span color="text_secondary">{ config.chain.currency.symbol }</chakra.span>
<span> ${ Number(data.coin_price).toLocaleString(undefined, { maximumFractionDigits: 2 }) }</span> <span> ${ Number(data.coin_price).toLocaleString(undefined, { maximumFractionDigits: 2 }) }</span>
</Skeleton> </Skeleton>
......
import { test, expect, devices } from '@playwright/experimental-ct-react';
import type { Locator } from '@playwright/test'; import type { Locator } from '@playwright/test';
import React from 'react'; import React from 'react';
...@@ -6,9 +5,8 @@ import * as blockMock from 'mocks/blocks/block'; ...@@ -6,9 +5,8 @@ import * as blockMock from 'mocks/blocks/block';
import * as dailyTxsMock from 'mocks/stats/daily_txs'; import * as dailyTxsMock from 'mocks/stats/daily_txs';
import * as statsMock from 'mocks/stats/index'; import * as statsMock from 'mocks/stats/index';
import * as txMock from 'mocks/txs/tx'; import * as txMock from 'mocks/txs/tx';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs'; import { test, expect, devices } from 'playwright/lib';
import TestApp from 'playwright/TestApp'; import TestApp from 'playwright/TestApp';
import buildApiUrl from 'playwright/utils/buildApiUrl';
import * as configs from 'playwright/utils/configs'; import * as configs from 'playwright/utils/configs';
import Home from './Home'; import Home from './Home';
...@@ -16,30 +14,19 @@ import Home from './Home'; ...@@ -16,30 +14,19 @@ import Home from './Home';
test.describe('default view', () => { test.describe('default view', () => {
let component: Locator; let component: Locator;
test.beforeEach(async({ page, mount }) => { test.beforeEach(async({ mount, mockApiResponse, mockAssetResponse }) => {
await page.route(buildApiUrl('stats'), (route) => route.fulfill({ await mockAssetResponse(statsMock.base.coin_image, './playwright/mocks/image_s.jpg');
status: 200, await mockApiResponse('stats', statsMock.base);
body: JSON.stringify(statsMock.base), await mockApiResponse('homepage_blocks', [
}));
await page.route(buildApiUrl('homepage_blocks'), (route) => route.fulfill({
status: 200,
body: JSON.stringify([
blockMock.base, blockMock.base,
blockMock.base2, blockMock.base2,
]), ]);
})); await mockApiResponse('homepage_txs', [
await page.route(buildApiUrl('homepage_txs'), (route) => route.fulfill({
status: 200,
body: JSON.stringify([
txMock.base, txMock.base,
txMock.withContractCreation, txMock.withContractCreation,
txMock.withTokenTransfer, txMock.withTokenTransfer,
]), ]);
})); await mockApiResponse('stats_charts_txs', dailyTxsMock.base);
await page.route(buildApiUrl('stats_charts_txs'), (route) => route.fulfill({
status: 200,
body: JSON.stringify(dailyTxsMock.base),
}));
component = await mount( component = await mount(
<TestApp> <TestApp>
...@@ -69,14 +56,13 @@ test.describe('default view', () => { ...@@ -69,14 +56,13 @@ test.describe('default view', () => {
test.describe('custom hero plate background', () => { test.describe('custom hero plate background', () => {
const IMAGE_URL = 'https://localhost:3000/my-image.png'; const IMAGE_URL = 'https://localhost:3000/my-image.png';
const extendedTest = test.extend({ test.beforeEach(async({ mockEnvs }) => {
context: contextWithEnvs([ await mockEnvs([
{ name: 'NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND', value: `no-repeat center/cover url(${ IMAGE_URL })` }, [ 'NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND', `no-repeat center/cover url(${ IMAGE_URL })` ],
// eslint-disable-next-line @typescript-eslint/no-explicit-any ]);
]) as any,
}); });
extendedTest('default view', async({ mount, page }) => { test('default view', async({ mount, page }) => {
await page.route(IMAGE_URL, (route) => { await page.route(IMAGE_URL, (route) => {
return route.fulfill({ return route.fulfill({
status: 200, status: 200,
...@@ -103,30 +89,19 @@ test.describe('custom hero plate background', () => { ...@@ -103,30 +89,19 @@ test.describe('custom hero plate background', () => {
test.describe('mobile', () => { test.describe('mobile', () => {
test.use({ viewport: devices['iPhone 13 Pro'].viewport }); test.use({ viewport: devices['iPhone 13 Pro'].viewport });
test('base view', async({ mount, page }) => { test('base view', async({ mount, page, mockAssetResponse, mockApiResponse }) => {
await page.route(buildApiUrl('stats'), (route) => route.fulfill({ await mockAssetResponse(statsMock.base.coin_image, './playwright/mocks/image_s.jpg');
status: 200, await mockApiResponse('stats', statsMock.base);
body: JSON.stringify(statsMock.base), await mockApiResponse('homepage_blocks', [
}));
await page.route(buildApiUrl('homepage_blocks'), (route) => route.fulfill({
status: 200,
body: JSON.stringify([
blockMock.base, blockMock.base,
blockMock.base2, blockMock.base2,
]), ]);
})); await mockApiResponse('homepage_txs', [
await page.route(buildApiUrl('homepage_txs'), (route) => route.fulfill({
status: 200,
body: JSON.stringify([
txMock.base, txMock.base,
txMock.withContractCreation, txMock.withContractCreation,
txMock.withTokenTransfer, txMock.withTokenTransfer,
]), ]);
})); await mockApiResponse('stats_charts_txs', dailyTxsMock.base);
await page.route(buildApiUrl('stats_charts_txs'), (route) => route.fulfill({
status: 200,
body: JSON.stringify(dailyTxsMock.base),
}));
const component = await mount( const component = await mount(
<TestApp> <TestApp>
......
import { Skeleton, Image, chakra } from '@chakra-ui/react';
import React from 'react';
import config from 'configs/app';
import useApiQuery from 'lib/api/useApiQuery';
import { HOMEPAGE_STATS } from 'stubs/stats';
import TokenLogoPlaceholder from './TokenLogoPlaceholder';
type Props = {
isLoading?: boolean;
className?: string;
}
const NativeTokenIcon = (props: Props) => {
const statsQueryResult = useApiQuery('stats', {
queryOptions: {
refetchOnMount: false,
placeholderData: HOMEPAGE_STATS,
},
});
if (props.isLoading || statsQueryResult.isPlaceholderData) {
return <Skeleton borderRadius="base" className={ props.className }/>;
}
return (
<Image
borderRadius="base"
className={ props.className }
src={ statsQueryResult.data?.coin_image || '' }
alt={ `${ config.chain.currency.symbol } logo` }
fallback={ <TokenLogoPlaceholder borderRadius="base" className={ props.className }/> }
fallbackStrategy={ statsQueryResult.data?.coin_image ? 'onError' : 'beforeLoadOrError' }
/>
);
};
export default chakra(NativeTokenIcon);
...@@ -7,7 +7,6 @@ import type { TokenInfo } from 'types/api/token'; ...@@ -7,7 +7,6 @@ import type { TokenInfo } from 'types/api/token';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import config from 'configs/app';
import * as EntityBase from 'ui/shared/entities/base/components'; import * as EntityBase from 'ui/shared/entities/base/components';
import TokenLogoPlaceholder from 'ui/shared/TokenLogoPlaceholder'; import TokenLogoPlaceholder from 'ui/shared/TokenLogoPlaceholder';
import TruncatedTextTooltip from 'ui/shared/TruncatedTextTooltip'; import TruncatedTextTooltip from 'ui/shared/TruncatedTextTooltip';
...@@ -168,16 +167,3 @@ export { ...@@ -168,16 +167,3 @@ export {
Content, Content,
Copy, Copy,
}; };
type NativeIconProps = Omit<IconProps, 'token'> & { src?: string | null };
const NATIVE_TOKEN_DATA = {
name: config.chain.currency.name || '',
symbol: '',
address: '',
type: 'ERC-20' as const,
};
export const NativeIcon = (props: NativeIconProps) => {
return <Icon token={{ ...NATIVE_TOKEN_DATA, icon_url: props.src || null }} { ...props }/>;
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment