Merge branch 'main' of github.com:blockscout/frontend into tom2drum/issue-1035
@@ -5,6 +5,9 @@ const RESTRICTED_MODULES = {
|
||||
{ name: '@metamask/providers', message: 'Please lazy-load @metamask/providers or use useProvider hook instead' },
|
||||
{ name: '@metamask/post-message-stream', message: 'Please lazy-load @metamask/post-message-stream or use useProvider hook instead' },
|
||||
],
|
||||
patterns: [
|
||||
'icons/*',
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
/out/
|
||||
/public/assets/
|
||||
/public/envs.js
|
||||
/public/icons/sprite.svg
|
||||
/public/icons/README.md
|
||||
/analyze
|
||||
|
||||
# production
|
||||
|
||||
@@ -265,7 +265,7 @@
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "format-svg",
|
||||
"script": "svg:format",
|
||||
"problemMatcher": [],
|
||||
"label": "format svg",
|
||||
"detail": "format svg files with svgo",
|
||||
@@ -318,6 +318,7 @@
|
||||
"main.L2",
|
||||
"poa_core",
|
||||
"eth_goerli",
|
||||
"sepolia",
|
||||
"eth",
|
||||
"rootstock",
|
||||
"polygon",
|
||||
|
||||
@@ -58,6 +58,7 @@ RUN ./collect_envs.sh ./docs/ENVS.md
|
||||
|
||||
# Build app for production
|
||||
RUN yarn build
|
||||
RUN yarn svg:build-sprite
|
||||
|
||||
|
||||
### FEATURE REPORTER
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# Set of ENVs for Sepolia testnet network explorer
|
||||
# https://eth-sepolia.blockscout.com/
|
||||
|
||||
# app configuration
|
||||
NEXT_PUBLIC_APP_PROTOCOL=http
|
||||
NEXT_PUBLIC_APP_HOST=localhost
|
||||
NEXT_PUBLIC_APP_PORT=3000
|
||||
|
||||
# blockchain parameters
|
||||
NEXT_PUBLIC_NETWORK_NAME=Sepolia
|
||||
NEXT_PUBLIC_NETWORK_SHORT_NAME=Sepolia
|
||||
NEXT_PUBLIC_NETWORK_ID=11155111
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
|
||||
NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation
|
||||
NEXT_PUBLIC_NETWORK_RPC_URL=https://eth-sepolia.public.blastapi.io
|
||||
NEXT_PUBLIC_IS_TESTNET=true
|
||||
|
||||
# api configuration
|
||||
NEXT_PUBLIC_API_HOST=eth-sepolia.blockscout.com
|
||||
NEXT_PUBLIC_API_BASE_PATH=/
|
||||
|
||||
# ui config
|
||||
## homepage
|
||||
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
|
||||
NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND='rgba(51, 53, 67, 1)'
|
||||
NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR='rgba(165, 252, 122, 1)'
|
||||
## sidebar
|
||||
NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/eth-sepolia.json
|
||||
NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/sepolia.svg
|
||||
NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/sepolia.svg
|
||||
NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/sepolia.png
|
||||
NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/sepolia.png
|
||||
NEXT_PUBLIC_OTHER_LINKS=[{'url':'https://sepolia.drpc.org?ref=559183','text':'Public RPC'}]
|
||||
## footer
|
||||
NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/sepolia.json
|
||||
##views
|
||||
NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES=[{'name':'LooksRare','collection_url':'https://sepolia.looksrare.org/collections/{hash}','instance_url':'https://sepolia.looksrare.org/collections/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/looks-rare.png'}]
|
||||
## misc
|
||||
NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Etherscan','baseUrl':'https://sepolia.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}},{'title':'Tenderly','baseUrl':'https://dashboard.tenderly.co','paths':{'tx':'/tx/sepolia'}}]
|
||||
|
||||
# app features
|
||||
NEXT_PUBLIC_APP_ENV=development
|
||||
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xbf69c7abc4fee283b59a9633dadfdaedde5c5ee0fba3e80a08b5b8a3acbd4363
|
||||
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
|
||||
NEXT_PUBLIC_AUTH_URL=http://localhost:3000
|
||||
NEXT_PUBLIC_LOGOUT_URL=https://blockscout-goerli.us.auth0.com/v2/logout
|
||||
NEXT_PUBLIC_MARKETPLACE_CONFIG_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/marketplace/eth-goerli.json
|
||||
NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/shrqUAcjgGJ4jU88C
|
||||
NEXT_PUBLIC_STATS_API_HOST=https://stats-sepolia.k8s-dev.blockscout.com
|
||||
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
|
||||
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
|
||||
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
|
||||
NEXT_PUBLIC_WEB3_WALLETS=['token_pocket','metamask']
|
||||
NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
|
||||
NEXT_PUBLIC_HAS_BEACON_CHAIN=true
|
||||
|
||||
#meta
|
||||
NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/sepolia-testnet.png
|
||||
@@ -182,7 +182,8 @@ We have 3 pre-configured projects. You can run your test with the desired projec
|
||||
| `yarn lint:eslint` | lint project files with ESLint |
|
||||
| `yarn lint:eslint:fix` | lint project files with ESLint and automatically fix problems |
|
||||
| `yarn lint:tsc` | compile project typescript files using TypeScript Compiler |
|
||||
| `yarn format-svg` | format and optimize SVG icons in the `/icons` folder using SVGO tool |
|
||||
| `yarn svg:format` | format and optimize SVG icons in the `/icons` folder using SVGO tool |
|
||||
| `yarn svg:build-sprite` | build SVG icons sprite |
|
||||
| **Testing** |
|
||||
| `yarn test:jest` | run all Jest unit tests |
|
||||
| `yarn test:jest:watch` | run all Jest unit tests in watch mode |
|
||||
|
||||
|
Before Width: | Height: | Size: 198 B After Width: | Height: | Size: 198 B |
|
Before Width: | Height: | Size: 215 B After Width: | Height: | Size: 215 B |
|
Before Width: | Height: | Size: 182 B After Width: | Height: | Size: 182 B |
|
Before Width: | Height: | Size: 228 B After Width: | Height: | Size: 228 B |
|
Before Width: | Height: | Size: 610 B After Width: | Height: | Size: 610 B |
@@ -4,28 +4,6 @@ import React from 'react';
|
||||
import type { NavItemInternal, NavItem, NavGroupItem } from 'types/client/navigation-items';
|
||||
|
||||
import config from 'configs/app';
|
||||
import abiIcon from 'icons/ABI.svg';
|
||||
import apiKeysIcon from 'icons/API.svg';
|
||||
import appsIcon from 'icons/apps.svg';
|
||||
import withdrawalsIcon from 'icons/arrows/north-east.svg';
|
||||
import depositsIcon from 'icons/arrows/south-east.svg';
|
||||
import blocksIcon from 'icons/block.svg';
|
||||
import gearIcon from 'icons/gear.svg';
|
||||
import globeIcon from 'icons/globe-b.svg';
|
||||
import graphQLIcon from 'icons/graphQL.svg';
|
||||
import outputRootsIcon from 'icons/output_roots.svg';
|
||||
import privateTagIcon from 'icons/privattags.svg';
|
||||
import publicTagIcon from 'icons/publictags.svg';
|
||||
import apiDocsIcon from 'icons/restAPI.svg';
|
||||
import rpcIcon from 'icons/RPC.svg';
|
||||
import statsIcon from 'icons/stats.svg';
|
||||
import tokensIcon from 'icons/token.svg';
|
||||
import topAccountsIcon from 'icons/top-accounts.svg';
|
||||
import transactionsIcon from 'icons/transactions.svg';
|
||||
import txnBatchIcon from 'icons/txn_batches.svg';
|
||||
import verifiedIcon from 'icons/verified.svg';
|
||||
import verifyContractIcon from 'icons/verify-contract.svg';
|
||||
import watchlistIcon from 'icons/watchlist.svg';
|
||||
import { rightLineArrow } from 'lib/html-entities';
|
||||
import UserAvatar from 'ui/shared/UserAvatar';
|
||||
|
||||
@@ -50,35 +28,43 @@ export default function useNavItems(): ReturnType {
|
||||
return React.useMemo(() => {
|
||||
let blockchainNavItems: Array<NavItem> | Array<Array<NavItem>> = [];
|
||||
|
||||
const topAccounts = !config.UI.views.address.hiddenViews?.top_accounts ? {
|
||||
const topAccounts: NavItem | null = !config.UI.views.address.hiddenViews?.top_accounts ? {
|
||||
text: 'Top accounts',
|
||||
nextRoute: { pathname: '/accounts' as const },
|
||||
icon: topAccountsIcon,
|
||||
icon: 'top-accounts',
|
||||
isActive: pathname === '/accounts',
|
||||
} : null;
|
||||
const blocks = {
|
||||
const blocks: NavItem | null = {
|
||||
text: 'Blocks',
|
||||
nextRoute: { pathname: '/blocks' as const },
|
||||
icon: blocksIcon,
|
||||
icon: 'block',
|
||||
isActive: pathname === '/blocks' || pathname === '/block/[height_or_hash]',
|
||||
};
|
||||
const txs = {
|
||||
const txs: NavItem | null = {
|
||||
text: 'Transactions',
|
||||
nextRoute: { pathname: '/txs' as const },
|
||||
icon: transactionsIcon,
|
||||
icon: 'transactions',
|
||||
isActive: pathname === '/txs' || pathname === '/tx/[hash]',
|
||||
};
|
||||
const verifiedContracts =
|
||||
// eslint-disable-next-line max-len
|
||||
{ text: 'Verified contracts', nextRoute: { pathname: '/verified-contracts' as const }, icon: verifiedIcon, isActive: pathname === '/verified-contracts' };
|
||||
const verifiedContracts: NavItem | null =
|
||||
{
|
||||
text: 'Verified contracts',
|
||||
nextRoute: { pathname: '/verified-contracts' as const },
|
||||
icon: 'verified',
|
||||
isActive: pathname === '/verified-contracts',
|
||||
};
|
||||
|
||||
if (config.features.zkEvmRollup.isEnabled) {
|
||||
blockchainNavItems = [
|
||||
[
|
||||
txs,
|
||||
blocks,
|
||||
// eslint-disable-next-line max-len
|
||||
{ text: 'Txn batches', nextRoute: { pathname: '/zkevm-l2-txn-batches' as const }, icon: txnBatchIcon, isActive: pathname === '/zkevm-l2-txn-batches' || pathname === '/zkevm-l2-txn-batch/[number]' },
|
||||
{
|
||||
text: 'Txn batches',
|
||||
nextRoute: { pathname: '/zkevm-l2-txn-batches' as const },
|
||||
icon: 'txn_batches',
|
||||
isActive: pathname === '/zkevm-l2-txn-batches' || pathname === '/zkevm-l2-txn-batch/[number]',
|
||||
},
|
||||
],
|
||||
[
|
||||
topAccounts,
|
||||
@@ -90,16 +76,16 @@ export default function useNavItems(): ReturnType {
|
||||
[
|
||||
txs,
|
||||
// eslint-disable-next-line max-len
|
||||
{ text: `Deposits (L1${ rightLineArrow }L2)`, nextRoute: { pathname: '/l2-deposits' as const }, icon: depositsIcon, isActive: pathname === '/l2-deposits' },
|
||||
{ text: `Deposits (L1${ rightLineArrow }L2)`, nextRoute: { pathname: '/l2-deposits' as const }, icon: 'arrows/south-east', isActive: pathname === '/l2-deposits' },
|
||||
// eslint-disable-next-line max-len
|
||||
{ text: `Withdrawals (L2${ rightLineArrow }L1)`, nextRoute: { pathname: '/l2-withdrawals' as const }, icon: withdrawalsIcon, isActive: pathname === '/l2-withdrawals' },
|
||||
{ text: `Withdrawals (L2${ rightLineArrow }L1)`, nextRoute: { pathname: '/l2-withdrawals' as const }, icon: 'arrows/north-east', isActive: pathname === '/l2-withdrawals' },
|
||||
],
|
||||
[
|
||||
blocks,
|
||||
// eslint-disable-next-line max-len
|
||||
{ text: 'Txn batches', nextRoute: { pathname: '/l2-txn-batches' as const }, icon: txnBatchIcon, isActive: pathname === '/l2-txn-batches' },
|
||||
{ text: 'Txn batches', nextRoute: { pathname: '/l2-txn-batches' as const }, icon: 'txn_batches', isActive: pathname === '/l2-txn-batches' },
|
||||
// eslint-disable-next-line max-len
|
||||
{ text: 'Output roots', nextRoute: { pathname: '/l2-output-roots' as const }, icon: outputRootsIcon, isActive: pathname === '/l2-output-roots' },
|
||||
{ text: 'Output roots', nextRoute: { pathname: '/l2-output-roots' as const }, icon: 'output_roots', isActive: pathname === '/l2-output-roots' },
|
||||
],
|
||||
[
|
||||
topAccounts,
|
||||
@@ -115,7 +101,7 @@ export default function useNavItems(): ReturnType {
|
||||
config.features.beaconChain.isEnabled && {
|
||||
text: 'Withdrawals',
|
||||
nextRoute: { pathname: '/withdrawals' as const },
|
||||
icon: withdrawalsIcon,
|
||||
icon: 'arrows/north-east',
|
||||
isActive: pathname === '/withdrawals',
|
||||
},
|
||||
].filter(Boolean);
|
||||
@@ -125,23 +111,23 @@ export default function useNavItems(): ReturnType {
|
||||
config.features.restApiDocs.isEnabled ? {
|
||||
text: 'REST API',
|
||||
nextRoute: { pathname: '/api-docs' as const },
|
||||
icon: apiDocsIcon,
|
||||
icon: 'restAPI',
|
||||
isActive: pathname === '/api-docs',
|
||||
} : null,
|
||||
config.features.graphqlApiDocs.isEnabled ? {
|
||||
text: 'GraphQL',
|
||||
nextRoute: { pathname: '/graphiql' as const },
|
||||
icon: graphQLIcon,
|
||||
icon: 'graphQL',
|
||||
isActive: pathname === '/graphiql',
|
||||
} : null,
|
||||
!config.UI.sidebar.hiddenLinks?.rpc_api && {
|
||||
text: 'RPC API',
|
||||
icon: rpcIcon,
|
||||
icon: 'RPC',
|
||||
url: 'https://docs.blockscout.com/for-users/api/rpc-endpoints',
|
||||
},
|
||||
!config.UI.sidebar.hiddenLinks?.eth_rpc_api && {
|
||||
text: 'Eth RPC API',
|
||||
icon: rpcIcon,
|
||||
icon: 'RPC',
|
||||
url: ' https://docs.blockscout.com/for-users/api/eth-rpc',
|
||||
},
|
||||
].filter(Boolean);
|
||||
@@ -149,42 +135,42 @@ export default function useNavItems(): ReturnType {
|
||||
const mainNavItems: ReturnType['mainNavItems'] = [
|
||||
{
|
||||
text: 'Blockchain',
|
||||
icon: globeIcon,
|
||||
icon: 'globe-b',
|
||||
isActive: blockchainNavItems.flat().some(item => isInternalItem(item) && item.isActive),
|
||||
subItems: blockchainNavItems,
|
||||
},
|
||||
{
|
||||
text: 'Tokens',
|
||||
nextRoute: { pathname: '/tokens' as const },
|
||||
icon: tokensIcon,
|
||||
icon: 'token',
|
||||
isActive: pathname.startsWith('/token'),
|
||||
},
|
||||
config.features.marketplace.isEnabled ? {
|
||||
text: 'Apps',
|
||||
nextRoute: { pathname: '/apps' as const },
|
||||
icon: appsIcon,
|
||||
icon: 'apps',
|
||||
isActive: pathname.startsWith('/app'),
|
||||
} : null,
|
||||
config.features.stats.isEnabled ? {
|
||||
text: 'Charts & stats',
|
||||
nextRoute: { pathname: '/stats' as const },
|
||||
icon: statsIcon,
|
||||
icon: 'stats',
|
||||
isActive: pathname === '/stats',
|
||||
} : null,
|
||||
apiNavItems.length > 0 && {
|
||||
text: 'API',
|
||||
icon: apiDocsIcon,
|
||||
icon: 'restAPI',
|
||||
isActive: apiNavItems.some(item => isInternalItem(item) && item.isActive),
|
||||
subItems: apiNavItems,
|
||||
},
|
||||
{
|
||||
text: 'Other',
|
||||
icon: gearIcon,
|
||||
icon: 'gear',
|
||||
subItems: [
|
||||
{
|
||||
text: 'Verify contract',
|
||||
nextRoute: { pathname: '/contract-verification' as const },
|
||||
icon: verifyContractIcon,
|
||||
icon: 'verify-contract',
|
||||
isActive: pathname.startsWith('/contract-verification'),
|
||||
},
|
||||
...config.UI.sidebar.otherLinks,
|
||||
@@ -196,35 +182,37 @@ export default function useNavItems(): ReturnType {
|
||||
{
|
||||
text: 'Watch list',
|
||||
nextRoute: { pathname: '/account/watchlist' as const },
|
||||
icon: watchlistIcon,
|
||||
icon: 'watchlist',
|
||||
isActive: pathname === '/account/watchlist',
|
||||
},
|
||||
{
|
||||
text: 'Private tags',
|
||||
nextRoute: { pathname: '/account/tag-address' as const },
|
||||
icon: privateTagIcon,
|
||||
icon: 'privattags',
|
||||
isActive: pathname === '/account/tag-address',
|
||||
},
|
||||
{
|
||||
text: 'Public tags',
|
||||
nextRoute: { pathname: '/account/public-tags-request' as const },
|
||||
icon: publicTagIcon, isActive: pathname === '/account/public-tags-request',
|
||||
icon: 'publictags',
|
||||
isActive: pathname === '/account/public-tags-request',
|
||||
},
|
||||
{
|
||||
text: 'API keys',
|
||||
nextRoute: { pathname: '/account/api-key' as const },
|
||||
icon: apiKeysIcon, isActive: pathname === '/account/api-key',
|
||||
icon: 'API',
|
||||
isActive: pathname === '/account/api-key',
|
||||
},
|
||||
{
|
||||
text: 'Custom ABI',
|
||||
nextRoute: { pathname: '/account/custom-abi' as const },
|
||||
icon: abiIcon,
|
||||
icon: 'ABI',
|
||||
isActive: pathname === '/account/custom-abi',
|
||||
},
|
||||
config.features.addressVerification.isEnabled && {
|
||||
text: 'Verified addrs',
|
||||
nextRoute: { pathname: '/account/verified-addresses' as const },
|
||||
icon: verifiedIcon,
|
||||
icon: 'verified',
|
||||
isActive: pathname === '/account/verified-addresses',
|
||||
},
|
||||
].filter(Boolean);
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
import type { WalletType, WalletInfo } from 'types/client/wallets';
|
||||
|
||||
import coinbaseIcon from 'icons/wallets/coinbase.svg';
|
||||
import metamaskIcon from 'icons/wallets/metamask.svg';
|
||||
import tokenPocketIcon from 'icons/wallets/token-pocket.svg';
|
||||
|
||||
export const WALLETS_INFO: Record<Exclude<WalletType, 'none'>, WalletInfo> = {
|
||||
metamask: {
|
||||
name: 'MetaMask',
|
||||
icon: metamaskIcon,
|
||||
icon: 'wallets/metamask',
|
||||
},
|
||||
coinbase: {
|
||||
name: 'Coinbase Wallet',
|
||||
icon: coinbaseIcon,
|
||||
icon: 'wallets/coinbase',
|
||||
},
|
||||
token_pocket: {
|
||||
name: 'TokenPocket',
|
||||
icon: tokenPocketIcon,
|
||||
icon: 'wallets/token-pocket',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
"lint:tsc": "tsc -p ./tsconfig.json",
|
||||
"lint:envs-validator:test": "cd ./deploy/tools/envs-validator && ./test.sh",
|
||||
"prepare": "husky install",
|
||||
"format-svg": "svgo -r ./icons",
|
||||
"svg:format": "svgo -r ./icons",
|
||||
"svg:build-sprite": "icons build -i ./icons -o ./public/icons --optimize",
|
||||
"test:pw": "./tools/scripts/pw.sh",
|
||||
"test:pw:local": "export NODE_PATH=$(pwd)/node_modules && yarn test:pw",
|
||||
"test:pw:docker": "docker run --rm --network host -v $(pwd):/work/ -w /work/ -it mcr.microsoft.com/playwright:v1.35.1-focal ./tools/scripts/pw.docker.sh",
|
||||
@@ -137,6 +138,7 @@
|
||||
"lint-staged": ">=10",
|
||||
"mockdate": "^3.0.5",
|
||||
"style-loader": "^3.3.1",
|
||||
"svg-icons-cli": "^0.0.5",
|
||||
"svgo": "^2.8.0",
|
||||
"ts-jest": "^29.0.3",
|
||||
"ts-node": "^10.9.1",
|
||||
|
||||
@@ -6,6 +6,7 @@ import React from 'react';
|
||||
import * as serverTiming from 'nextjs/utils/serverTiming';
|
||||
|
||||
import theme from 'theme';
|
||||
import * as svgSprite from 'ui/shared/IconSvg';
|
||||
|
||||
class MyDocument extends Document {
|
||||
static async getInitialProps(ctx: DocumentContext) {
|
||||
@@ -48,6 +49,8 @@ class MyDocument extends Document {
|
||||
<link rel="icon" sizes="16x16" type="image/png"href="/favicon/favicon-16x16.png"/>
|
||||
<link rel="apple-touch-icon" href="/favicon/apple-touch-icon-180x180.png"/>
|
||||
<link rel="mask-icon" href="/favicon/safari-pinned-tab.svg"/>
|
||||
|
||||
<link rel="preload" as="image" href={ svgSprite.href }/>
|
||||
</Head>
|
||||
<body>
|
||||
<ColorModeScript initialColorMode={ theme.config.initialColorMode }/>
|
||||
|
||||
@@ -9,5 +9,6 @@
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/playwright/envs.js"></script>
|
||||
<script type="module" src="/playwright/index.ts"></script>
|
||||
<link rel="preload" as="image" href="/public/icons/sprite.svg"/>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
// This file is generated by npm run build:icons
|
||||
|
||||
export type IconName =
|
||||
| "ABI"
|
||||
| "API"
|
||||
| "apps"
|
||||
| "arrows/down-right"
|
||||
| "arrows/east-mini"
|
||||
| "arrows/east"
|
||||
| "arrows/north-east"
|
||||
| "arrows/south-east"
|
||||
| "arrows/up-down"
|
||||
| "block_slim"
|
||||
| "block"
|
||||
| "brands/safe"
|
||||
| "burger"
|
||||
| "check"
|
||||
| "clock-light"
|
||||
| "clock"
|
||||
| "coins/bitcoin"
|
||||
| "collection"
|
||||
| "contract_verified"
|
||||
| "contract"
|
||||
| "copy"
|
||||
| "cross"
|
||||
| "delete"
|
||||
| "discussions"
|
||||
| "docs"
|
||||
| "donate"
|
||||
| "edit"
|
||||
| "email-sent"
|
||||
| "email"
|
||||
| "empty_search_result"
|
||||
| "error-pages/404"
|
||||
| "error-pages/422"
|
||||
| "error-pages/429"
|
||||
| "error-pages/500"
|
||||
| "explorer"
|
||||
| "files/csv"
|
||||
| "files/image"
|
||||
| "files/json"
|
||||
| "files/placeholder"
|
||||
| "files/sol"
|
||||
| "files/yul"
|
||||
| "filter"
|
||||
| "finalized"
|
||||
| "flame"
|
||||
| "gas"
|
||||
| "gear"
|
||||
| "globe-b"
|
||||
| "globe"
|
||||
| "graphQL"
|
||||
| "info"
|
||||
| "key"
|
||||
| "link"
|
||||
| "lock"
|
||||
| "minus"
|
||||
| "monaco/file"
|
||||
| "monaco/folder-open"
|
||||
| "monaco/folder"
|
||||
| "monaco/solidity"
|
||||
| "monaco/vyper"
|
||||
| "moon-with-star"
|
||||
| "moon"
|
||||
| "networks"
|
||||
| "networks/icon-placeholder"
|
||||
| "networks/logo-placeholder"
|
||||
| "nft_shield"
|
||||
| "output_roots"
|
||||
| "plus"
|
||||
| "privattags"
|
||||
| "profile"
|
||||
| "publictags_slim"
|
||||
| "publictags"
|
||||
| "qr_code"
|
||||
| "repeat_arrow"
|
||||
| "restAPI"
|
||||
| "rocket"
|
||||
| "RPC"
|
||||
| "scope"
|
||||
| "score/score-not-ok"
|
||||
| "score/score-ok"
|
||||
| "search"
|
||||
| "social/canny"
|
||||
| "social/coingecko"
|
||||
| "social/coinmarketcap"
|
||||
| "social/defi_llama"
|
||||
| "social/discord_filled"
|
||||
| "social/discord"
|
||||
| "social/facebook_filled"
|
||||
| "social/git"
|
||||
| "social/github_filled"
|
||||
| "social/linkedin_filled"
|
||||
| "social/medium_filled"
|
||||
| "social/opensea_filled"
|
||||
| "social/reddit_filled"
|
||||
| "social/slack_filled"
|
||||
| "social/stats"
|
||||
| "social/telega"
|
||||
| "social/telegram_filled"
|
||||
| "social/tweet"
|
||||
| "social/twitter_filled"
|
||||
| "star_filled"
|
||||
| "star_outline"
|
||||
| "stats"
|
||||
| "status/error"
|
||||
| "status/pending"
|
||||
| "status/success"
|
||||
| "status/warning"
|
||||
| "sun"
|
||||
| "testnet"
|
||||
| "token-placeholder"
|
||||
| "token"
|
||||
| "tokens"
|
||||
| "tokens/xdai"
|
||||
| "top-accounts"
|
||||
| "transactions_slim"
|
||||
| "transactions"
|
||||
| "txn_batches_slim"
|
||||
| "txn_batches"
|
||||
| "unfinalized"
|
||||
| "uniswap"
|
||||
| "verified_token"
|
||||
| "verified"
|
||||
| "verify-contract"
|
||||
| "vertical_dots"
|
||||
| "wallet"
|
||||
| "wallets/coinbase"
|
||||
| "wallets/metamask"
|
||||
| "wallets/token-pocket"
|
||||
| "watchlist";
|
||||
|
||||
@@ -5,11 +5,11 @@ module.exports = {
|
||||
params: {
|
||||
overrides: {
|
||||
removeViewBox: false,
|
||||
removeHiddenElems: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
'removeDimensions',
|
||||
'prefixIds',
|
||||
],
|
||||
js2svg: {
|
||||
indent: 2,
|
||||
|
||||
@@ -19,6 +19,9 @@ dotenv \
|
||||
-e $config_file \
|
||||
-- bash -c './deploy/scripts/download_assets.sh ./public/assets'
|
||||
|
||||
yarn svg:build-sprite
|
||||
echo ""
|
||||
|
||||
# generate envs.js file and run the app
|
||||
dotenv \
|
||||
-v NEXT_PUBLIC_GIT_COMMIT_SHA=$(git rev-parse --short HEAD) \
|
||||
|
||||
@@ -8,6 +8,9 @@ dotenv \
|
||||
-e .env \
|
||||
-- bash -c './deploy/scripts/download_assets.sh ./public/assets'
|
||||
|
||||
yarn svg:build-sprite
|
||||
echo ""
|
||||
|
||||
# generate envs.js file and run the app
|
||||
dotenv \
|
||||
-v NEXT_PUBLIC_GIT_COMMIT_SHA=$(git rev-parse --short HEAD) \
|
||||
|
||||
@@ -8,6 +8,8 @@ dotenv \
|
||||
-e $config_file \
|
||||
-- bash -c './deploy/scripts/make_envs_script.sh ./playwright/envs.js'
|
||||
|
||||
yarn svg:build-sprite
|
||||
|
||||
dotenv \
|
||||
-v NODE_OPTIONS=\"--max-old-space-size=4096\" \
|
||||
-e $config_file \
|
||||
|
||||
@@ -2,8 +2,10 @@ import type React from 'react';
|
||||
|
||||
import type { Route } from 'nextjs-routes';
|
||||
|
||||
import type { IconName } from 'ui/shared/IconSvg';
|
||||
|
||||
type NavIconOrComponent = {
|
||||
icon?: React.FunctionComponent<React.SVGAttributes<SVGElement>>;
|
||||
icon?: IconName;
|
||||
} | {
|
||||
iconComponent?: React.FC<{size?: number}>;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { ArrayElement } from 'types/utils';
|
||||
|
||||
import type { IconName } from 'ui/shared/IconSvg';
|
||||
|
||||
export const SUPPORTED_WALLETS = [
|
||||
'metamask',
|
||||
'coinbase',
|
||||
@@ -10,5 +12,5 @@ export type WalletType = ArrayElement<typeof SUPPORTED_WALLETS>;
|
||||
|
||||
export interface WalletInfo {
|
||||
name: string;
|
||||
icon: React.ElementType;
|
||||
icon: IconName;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { chakra, Icon, Tooltip, Hide, Skeleton, Flex } from '@chakra-ui/react';
|
||||
import { chakra, Tooltip, Hide, Skeleton, Flex } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { CsvExportParams } from 'types/client/address';
|
||||
@@ -6,9 +6,9 @@ import type { CsvExportParams } from 'types/client/address';
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import svgFileIcon from 'icons/files/csv.svg';
|
||||
import useIsInitialLoading from 'lib/hooks/useIsInitialLoading';
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
|
||||
interface Props {
|
||||
@@ -47,7 +47,7 @@ const AddressCsvExportLink = ({ className, address, params, isLoading }: Props)
|
||||
href={ route({ pathname: '/csv-export', query: { ...params, address } }) }
|
||||
flexShrink={ 0 }
|
||||
>
|
||||
<Icon as={ svgFileIcon } boxSize={{ base: '30px', lg: 6 }}/>
|
||||
<IconSvg name="files/csv" boxSize={{ base: '30px', lg: 6 }}/>
|
||||
<Hide ssr={ false } below="lg"><chakra.span ml={ 1 }>Download CSV</chakra.span></Hide>
|
||||
</LinkInternal>
|
||||
</Tooltip>
|
||||
|
||||
@@ -5,8 +5,6 @@ import React from 'react';
|
||||
import type { NFTTokenType } from 'types/api/token';
|
||||
import type { PaginationParams } from 'ui/shared/pagination/types';
|
||||
|
||||
import listIcon from 'icons/apps.svg';
|
||||
import collectionIcon from 'icons/collection.svg';
|
||||
import { useAppContext } from 'lib/contexts/app';
|
||||
import * as cookies from 'lib/cookies';
|
||||
import getFilterValuesFromQuery from 'lib/getFilterValuesFromQuery';
|
||||
@@ -125,8 +123,8 @@ const AddressTokens = () => {
|
||||
defaultValue={ nftDisplayType }
|
||||
name="type"
|
||||
options={ [
|
||||
{ title: 'By collection', value: 'collection', icon: collectionIcon, onlyIcon: isMobile },
|
||||
{ title: 'List', value: 'list', icon: listIcon, onlyIcon: isMobile },
|
||||
{ title: 'By collection', value: 'collection', icon: 'collection', onlyIcon: isMobile },
|
||||
{ title: 'List', value: 'list', icon: 'apps', onlyIcon: isMobile },
|
||||
] }
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
Text,
|
||||
Grid,
|
||||
Button,
|
||||
Icon,
|
||||
chakra,
|
||||
Popover,
|
||||
PopoverTrigger,
|
||||
@@ -19,10 +18,9 @@ import React from 'react';
|
||||
|
||||
import { SolidityscanReport } from 'types/api/contract';
|
||||
|
||||
import scoreNotOkIcon from 'icons/score/score-not-ok.svg';
|
||||
import scoreOkIcon from 'icons/score/score-ok.svg';
|
||||
import useApiQuery from 'lib/api/useApiQuery';
|
||||
import { SOLIDITYSCAN_REPORT } from 'stubs/contract';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import LinkExternal from 'ui/shared/LinkExternal';
|
||||
|
||||
type DistributionItem = {
|
||||
@@ -125,7 +123,7 @@ const SolidityscanReport = ({ className, hash }: Props) => {
|
||||
h="32px"
|
||||
flexShrink={ 0 }
|
||||
>
|
||||
<Icon as={ score < 80 ? scoreNotOkIcon : scoreOkIcon } boxSize={ 5 } mr={ 1 }/>
|
||||
<IconSvg name={ score < 80 ? 'score/score-not-ok' : 'score/score-ok' } boxSize={ 5 } mr={ 1 }/>
|
||||
{ score }
|
||||
</Button>
|
||||
</Skeleton>
|
||||
@@ -143,7 +141,7 @@ const SolidityscanReport = ({ className, hash }: Props) => {
|
||||
mr={ 3 }
|
||||
>
|
||||
<Center position="absolute" w="38px" h="38px" top="5px" right="5px" bg={ popoverBgColor } borderRadius="20px">
|
||||
<Icon as={ score < 80 ? scoreNotOkIcon : scoreOkIcon } boxSize={ 5 } color={ scoreColor }/>
|
||||
<IconSvg name={ score < 80 ? 'score/score-not-ok' : 'score/score-ok' } boxSize={ 5 } color={ scoreColor }/>
|
||||
</Center>
|
||||
</Box>
|
||||
<Box>
|
||||
|
||||
@@ -78,6 +78,31 @@ test('verified with changed byte code socket', async({ mount, page, createSocket
|
||||
await expect(component).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test('verified via lookup in eth_bytecode_db', async({ mount, page, createSocket }) => {
|
||||
await page.route(CONTRACT_API_URL, (route) => route.fulfill({
|
||||
status: 200,
|
||||
body: JSON.stringify(contractMock.nonVerified),
|
||||
}));
|
||||
await page.route('https://cdn.jsdelivr.net/npm/[email protected]/**', (route) => route.abort());
|
||||
|
||||
await mount(
|
||||
<TestApp withSocket>
|
||||
<ContractCode addressHash={ addressHash }/>
|
||||
</TestApp>,
|
||||
{ hooksConfig },
|
||||
);
|
||||
|
||||
const socket = await createSocket();
|
||||
const channel = await socketServer.joinChannel(socket, 'addresses:' + addressHash.toLowerCase());
|
||||
|
||||
await page.waitForResponse(CONTRACT_API_URL);
|
||||
socketServer.sendMessage(socket, channel, 'smart_contract_was_verified', {});
|
||||
|
||||
const request = await page.waitForRequest(CONTRACT_API_URL);
|
||||
|
||||
expect(request).toBeTruthy();
|
||||
});
|
||||
|
||||
test('verified with multiple sources', async({ mount, page }) => {
|
||||
await page.route(CONTRACT_API_URL, (route) => route.fulfill({
|
||||
status: 200,
|
||||
|
||||
@@ -38,7 +38,6 @@ const ContractCode = ({ addressHash, noSocket }: Props) => {
|
||||
const [ isChangedBytecodeSocket, setIsChangedBytecodeSocket ] = React.useState<boolean>();
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
const refetchQueries = queryClient.refetchQueries;
|
||||
const addressInfo = queryClient.getQueryData<AddressInfo>(getResourceKey('address', { pathParams: { hash: addressHash } }));
|
||||
|
||||
const { data, isPlaceholderData, isError } = useApiQuery('contract', {
|
||||
@@ -55,13 +54,13 @@ const ContractCode = ({ addressHash, noSocket }: Props) => {
|
||||
}, [ ]);
|
||||
|
||||
const handleContractWasVerifiedMessage: SocketMessage.SmartContractWasVerified['handler'] = React.useCallback(() => {
|
||||
refetchQueries({
|
||||
queryClient.refetchQueries({
|
||||
queryKey: getResourceKey('address', { pathParams: { hash: addressHash } }),
|
||||
});
|
||||
refetchQueries({
|
||||
queryClient.refetchQueries({
|
||||
queryKey: getResourceKey('contract', { pathParams: { hash: addressHash } }),
|
||||
});
|
||||
}, [ addressHash, refetchQueries ]);
|
||||
}, [ addressHash, queryClient ]);
|
||||
|
||||
const enableQuery = React.useCallback(() => setIsQueryEnabled(true), []);
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
Button,
|
||||
Flex,
|
||||
Heading,
|
||||
Icon,
|
||||
Modal,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
@@ -20,11 +19,10 @@ import React from 'react';
|
||||
|
||||
import type { SmartContractExternalLibrary } from 'types/api/contract';
|
||||
|
||||
import arrowIcon from 'icons/arrows/east-mini.svg';
|
||||
import iconWarning from 'icons/status/warning.svg';
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import { apos } from 'lib/html-entities';
|
||||
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
@@ -66,8 +64,8 @@ const ContractExternalLibraries = ({ className, data }: Props) => {
|
||||
aria-label="View external libraries"
|
||||
>
|
||||
<span>{ data.length } { data.length > 1 ? 'Libraries' : 'Library' } </span>
|
||||
<Icon as={ iconWarning } boxSize={ 5 } color="orange.400" ml="2px"/>
|
||||
<Icon as={ arrowIcon } transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } transitionDuration="faster" boxSize={ 5 } ml={ 2 }/>
|
||||
<IconSvg name="status/warning" boxSize={ 5 } color="orange.400" ml="2px"/>
|
||||
<IconSvg name="arrows/east-mini" transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } transitionDuration="faster" boxSize={ 5 } ml={ 2 }/>
|
||||
</Button>
|
||||
);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Button, chakra, Flex, Icon, Text } from '@chakra-ui/react';
|
||||
import { Box, Button, chakra, Flex, Text } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
import type { SubmitHandler } from 'react-hook-form';
|
||||
import { useForm, FormProvider } from 'react-hook-form';
|
||||
@@ -7,8 +7,8 @@ import type { MethodFormFields, ContractMethodCallResult } from './types';
|
||||
import type { SmartContractMethodInput, SmartContractMethod } from 'types/api/contract';
|
||||
|
||||
import config from 'configs/app';
|
||||
import arrowIcon from 'icons/arrows/down-right.svg';
|
||||
import * as mixpanel from 'lib/mixpanel/index';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
import ContractMethodCallableRow from './ContractMethodCallableRow';
|
||||
import { formatFieldValues, transformFieldsToArgs } from './utils';
|
||||
@@ -165,7 +165,7 @@ const ContractMethodCallable = <T extends SmartContractMethod>({ data, onSubmit,
|
||||
</FormProvider>
|
||||
{ 'outputs' in data && !isWrite && data.outputs.length > 0 && (
|
||||
<Flex mt={ 3 } fontSize="sm">
|
||||
<Icon as={ arrowIcon } boxSize={ 5 } mr={ 1 }/>
|
||||
<IconSvg name="arrows/down-right" boxSize={ 5 } mr={ 1 }/>
|
||||
<Text>{ data.outputs.map(({ type, name }) => [ name, type ].join(' ')).join(', ') }</Text>
|
||||
</Flex>
|
||||
) }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex, Icon, IconButton } from '@chakra-ui/react';
|
||||
import { Flex, IconButton } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
import type { Control, UseFormGetValues, UseFormSetValue } from 'react-hook-form';
|
||||
import { useFieldArray } from 'react-hook-form';
|
||||
@@ -6,8 +6,7 @@ import { useFieldArray } from 'react-hook-form';
|
||||
import type { MethodFormFields } from './types';
|
||||
import type { SmartContractMethodArgType } from 'types/api/contract';
|
||||
|
||||
import minusIcon from 'icons/minus.svg';
|
||||
import plusIcon from 'icons/plus.svg';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
import ContractMethodField from './ContractMethodField';
|
||||
|
||||
@@ -80,7 +79,7 @@ const ContractMethodFieldArray = ({ control, name, setValue, getValues, isDisabl
|
||||
h="30px"
|
||||
flexShrink={ 0 }
|
||||
onClick={ handleRemoveButtonClick }
|
||||
icon={ <Icon as={ minusIcon } boxSize={ 4 }/> }
|
||||
icon={ <IconSvg name="minus" boxSize={ 4 }/> }
|
||||
isDisabled={ isDisabled }
|
||||
/>
|
||||
) }
|
||||
@@ -93,7 +92,7 @@ const ContractMethodFieldArray = ({ control, name, setValue, getValues, isDisabl
|
||||
h="30px"
|
||||
flexShrink={ 0 }
|
||||
onClick={ handleAddButtonClick }
|
||||
icon={ <Icon as={ plusIcon } boxSize={ 4 }/> }
|
||||
icon={ <IconSvg name="plus" boxSize={ 4 }/> }
|
||||
isDisabled={ isDisabled }
|
||||
/>
|
||||
) }
|
||||
|
||||
@@ -8,15 +8,13 @@ import {
|
||||
Button,
|
||||
List,
|
||||
ListItem,
|
||||
Icon,
|
||||
useDisclosure,
|
||||
Input,
|
||||
} from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import iconEastMini from 'icons/arrows/east-mini.svg';
|
||||
import iconCheck from 'icons/check.svg';
|
||||
import { times } from 'lib/html-entities';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
interface Props {
|
||||
onClick: (power: number) => void;
|
||||
@@ -80,7 +78,7 @@ const ContractMethodFieldZeroes = ({ onClick, isDisabled }: Props) => {
|
||||
onClick={ onToggle }
|
||||
isDisabled={ isDisabled }
|
||||
>
|
||||
<Icon as={ iconEastMini } transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } boxSize={ 6 }/>
|
||||
<IconSvg name="arrows/east-mini" transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } boxSize={ 6 }/>
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<Portal>
|
||||
@@ -99,7 +97,7 @@ const ContractMethodFieldZeroes = ({ onClick, isDisabled }: Props) => {
|
||||
cursor="pointer"
|
||||
>
|
||||
<span>10*{ id }</span>
|
||||
{ selectedOption === id && <Icon as={ iconCheck } boxSize={ 6 } color="blue.600"/> }
|
||||
{ selectedOption === id && <IconSvg name="check" boxSize={ 6 } color="blue.600"/> }
|
||||
</ListItem>
|
||||
)) }
|
||||
<ListItem
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, Box, Icon, Tooltip, useClipboard, useDisclosure } from '@chakra-ui/react';
|
||||
import { AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, Box, Tooltip, useClipboard, useDisclosure } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
import { Element } from 'react-scroll';
|
||||
|
||||
@@ -7,8 +7,8 @@ import type { SmartContractMethod } from 'types/api/contract';
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import iconLink from 'icons/link.svg';
|
||||
import Hint from 'ui/shared/Hint';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
interface Props<T extends SmartContractMethod> {
|
||||
data: T;
|
||||
@@ -58,7 +58,7 @@ const ContractMethodsAccordionItem = <T extends SmartContractMethod>({ data, ind
|
||||
onMouseEnter={ onOpen }
|
||||
onMouseLeave={ onClose }
|
||||
>
|
||||
<Icon as={ iconLink } boxSize={ 5 }/>
|
||||
<IconSvg name="link" boxSize={ 5 }/>
|
||||
</Box>
|
||||
</Tooltip>
|
||||
) }
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { Icon, chakra, Tooltip, IconButton, useDisclosure } from '@chakra-ui/react';
|
||||
import { chakra, Tooltip, IconButton, useDisclosure } from '@chakra-ui/react';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
|
||||
import config from 'configs/app';
|
||||
import starFilledIcon from 'icons/star_filled.svg';
|
||||
import starOutlineIcon from 'icons/star_outline.svg';
|
||||
import { getResourceKey } from 'lib/api/useApiQuery';
|
||||
import useIsAccountActionAllowed from 'lib/hooks/useIsAccountActionAllowed';
|
||||
import usePreventFocusAfterModalClosing from 'lib/hooks/usePreventFocusAfterModalClosing';
|
||||
import * as mixpanel from 'lib/mixpanel/index';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import WatchlistAddModal from 'ui/watchlist/AddressModal/AddressModal';
|
||||
import DeleteAddressModal from 'ui/watchlist/DeleteAddressModal';
|
||||
|
||||
@@ -73,7 +72,7 @@ const AddressFavoriteButton = ({ className, hash, watchListId }: Props) => {
|
||||
pr="6px"
|
||||
flexShrink={ 0 }
|
||||
onClick={ handleClick }
|
||||
icon={ <Icon as={ watchListId ? starFilledIcon : starOutlineIcon } boxSize={ 5 }/> }
|
||||
icon={ <IconSvg name={ watchListId ? 'star_filled' : 'star_outline' } boxSize={ 5 }/> }
|
||||
onFocusCapture={ onFocusCapture }
|
||||
/>
|
||||
</Tooltip>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
chakra,
|
||||
Alert,
|
||||
Icon,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalContent,
|
||||
@@ -22,10 +21,10 @@ import React from 'react';
|
||||
|
||||
import type { Address as AddressType } from 'types/api/address';
|
||||
|
||||
import qrCodeIcon from 'icons/qr_code.svg';
|
||||
import getPageType from 'lib/mixpanel/getPageType';
|
||||
import * as mixpanel from 'lib/mixpanel/index';
|
||||
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
const SVG_OPTIONS = {
|
||||
margin: 0,
|
||||
@@ -78,7 +77,7 @@ const AddressQrCode = ({ address, className, isLoading }: Props) => {
|
||||
pl="6px"
|
||||
pr="6px"
|
||||
onClick={ onOpen }
|
||||
icon={ <Icon as={ qrCodeIcon } boxSize={ 5 }/> }
|
||||
icon={ <IconSvg name="qr_code" boxSize={ 5 }/> }
|
||||
flexShrink={ 0 }
|
||||
/>
|
||||
</Tooltip>
|
||||
|
||||
@@ -5,13 +5,12 @@ import React from 'react';
|
||||
import type { InternalTransaction } from 'types/api/internalTransaction';
|
||||
|
||||
import config from 'configs/app';
|
||||
import eastArrowIcon from 'icons/arrows/east.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import Tag from 'ui/shared/chakra/Tag';
|
||||
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import InOutTag from 'ui/shared/InOutTag';
|
||||
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
|
||||
import TxStatus from 'ui/shared/statusTag/TxStatus';
|
||||
@@ -76,7 +75,7 @@ const TxInternalsListItem = ({
|
||||
/>
|
||||
{ (isIn || isOut) ?
|
||||
<InOutTag isIn={ isIn } isOut={ isOut } isLoading={ isLoading }/> :
|
||||
<Icon as={ eastArrowIcon } boxSize={ 6 } color="gray.500" isLoading={ isLoading }/>
|
||||
<IconSvg name="arrows/east" boxSize={ 6 } color="gray.500" isLoading={ isLoading }/>
|
||||
}
|
||||
{ toData && (
|
||||
<AddressEntity
|
||||
|
||||
@@ -5,13 +5,12 @@ import React from 'react';
|
||||
import type { InternalTransaction } from 'types/api/internalTransaction';
|
||||
|
||||
import config from 'configs/app';
|
||||
import rightArrowIcon from 'icons/arrows/east.svg';
|
||||
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import Tag from 'ui/shared/chakra/Tag';
|
||||
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import InOutTag from 'ui/shared/InOutTag';
|
||||
import TxStatus from 'ui/shared/statusTag/TxStatus';
|
||||
import { TX_INTERNALS_ITEMS } from 'ui/tx/internals/utils';
|
||||
@@ -88,7 +87,7 @@ const AddressIntTxsTableItem = ({
|
||||
<Td px={ 0 } verticalAlign="middle">
|
||||
{ (isIn || isOut) ?
|
||||
<InOutTag isIn={ isIn } isOut={ isOut } isLoading={ isLoading } w="100%"/> :
|
||||
<Icon as={ rightArrowIcon } boxSize={ 6 } color="gray.500" isLoading={ isLoading }/>
|
||||
<IconSvg name="arrows/east" boxSize={ 6 } color="gray.500" isLoading={ isLoading }/>
|
||||
}
|
||||
</Td>
|
||||
<Td verticalAlign="middle">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Flex, Icon, IconButton, Skeleton, Tooltip } from '@chakra-ui/react';
|
||||
import { Box, Flex, IconButton, Skeleton, Tooltip } from '@chakra-ui/react';
|
||||
import { useQueryClient, useIsFetching } from '@tanstack/react-query';
|
||||
import _sumBy from 'lodash/sumBy';
|
||||
import NextLink from 'next/link';
|
||||
@@ -7,11 +7,11 @@ import React from 'react';
|
||||
|
||||
import type { Address } from 'types/api/address';
|
||||
|
||||
import walletIcon from 'icons/wallet.svg';
|
||||
import { getResourceKey } from 'lib/api/useApiQuery';
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import * as mixpanel from 'lib/mixpanel/index';
|
||||
import getQueryParamString from 'lib/router/getQueryParamString';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
import useFetchTokens from '../utils/useFetchTokens';
|
||||
import TokenSelectDesktop from './TokenSelectDesktop';
|
||||
@@ -69,7 +69,7 @@ const TokenSelect = ({ onClick }: Props) => {
|
||||
size="sm"
|
||||
pl="6px"
|
||||
pr="6px"
|
||||
icon={ <Icon as={ walletIcon } boxSize={ 5 }/> }
|
||||
icon={ <IconSvg name="wallet" boxSize={ 5 }/> }
|
||||
as="a"
|
||||
onClick={ handleIconButtonClick }
|
||||
/>
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { Box, Button, Icon, Skeleton, Text, useColorModeValue } from '@chakra-ui/react';
|
||||
import { Box, Button, Skeleton, Text, useColorModeValue } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { FormattedData } from './types';
|
||||
|
||||
import arrowIcon from 'icons/arrows/east-mini.svg';
|
||||
import tokensIcon from 'icons/tokens.svg';
|
||||
import * as mixpanel from 'lib/mixpanel/index';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
import { getTokensTotalInfo } from '../utils/tokenUtils';
|
||||
|
||||
@@ -41,10 +40,10 @@ const TokenSelectButton = ({ isOpen, isLoading, onClick, data }: Props, ref: Rea
|
||||
onClick={ handleClick }
|
||||
aria-label="Token select"
|
||||
>
|
||||
<Icon as={ tokensIcon } boxSize={ 4 } mr={ 2 }/>
|
||||
<IconSvg name="tokens" boxSize={ 4 } mr={ 2 }/>
|
||||
<Text fontWeight={ 600 }>{ prefix }{ num }</Text>
|
||||
<Text whiteSpace="pre" variant="secondary" fontWeight={ 400 }> ({ prefix }${ usd.toFormat(2) })</Text>
|
||||
<Icon as={ arrowIcon } transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } transitionDuration="faster" boxSize={ 5 } ml={ 3 }/>
|
||||
<IconSvg name="arrows/east-mini" transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } transitionDuration="faster" boxSize={ 5 } ml={ 3 }/>
|
||||
</Button>
|
||||
{ isLoading && !isOpen && <Skeleton h="100%" w="100%" position="absolute" top={ 0 } left={ 0 } bgColor={ skeletonBgColor }/> }
|
||||
</Box>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Icon, Text, Box, Input, InputGroup, InputLeftElement, useColorModeValue, Flex, Link } from '@chakra-ui/react';
|
||||
import { Text, Box, Input, InputGroup, InputLeftElement, useColorModeValue, Flex, Link } from '@chakra-ui/react';
|
||||
import _sumBy from 'lodash/sumBy';
|
||||
import type { ChangeEvent } from 'react';
|
||||
import React from 'react';
|
||||
@@ -6,8 +6,7 @@ import React from 'react';
|
||||
import type { FormattedData } from './types';
|
||||
import type { TokenType } from 'types/api/token';
|
||||
|
||||
import arrowIcon from 'icons/arrows/east.svg';
|
||||
import searchIcon from 'icons/search.svg';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
import type { Sort } from '../utils/tokenUtils';
|
||||
import { sortTokenGroups, sortingFns } from '../utils/tokenUtils';
|
||||
@@ -32,7 +31,7 @@ const TokenSelectMenu = ({ erc20sort, erc1155sort, filteredData, onInputChange,
|
||||
<>
|
||||
<InputGroup size="xs" mb={ 5 }>
|
||||
<InputLeftElement >
|
||||
<Icon as={ searchIcon } boxSize={ 4 } color={ searchIconColor }/>
|
||||
<IconSvg name="search" boxSize={ 4 } color={ searchIconColor }/>
|
||||
</InputLeftElement>
|
||||
<Input
|
||||
paddingInlineStart="38px"
|
||||
@@ -72,7 +71,7 @@ const TokenSelectMenu = ({ erc20sort, erc1155sort, filteredData, onInputChange,
|
||||
<Text mb={ 3 } color="gray.500" fontWeight={ 600 } fontSize="sm">{ type } tokens ({ numPrefix }{ tokenInfo.items.length })</Text>
|
||||
{ hasSort && (
|
||||
<Link data-type={ type } onClick={ onSortClick } aria-label={ `Sort ${ type } tokens` }>
|
||||
<Icon as={ arrowIcon } boxSize={ 5 } transform={ arrowTransform } transitionDuration="faster"/>
|
||||
<IconSvg name="arrows/east" boxSize={ 5 } transform={ arrowTransform } transitionDuration="faster"/>
|
||||
</Link>
|
||||
) }
|
||||
</Flex>
|
||||
|
||||
@@ -22,7 +22,13 @@ const ERC20TokensTableItem = ({
|
||||
} = getCurrencyValue({ value: value, exchangeRate: token.exchange_rate, decimals: token.decimals, accuracy: 8, accuracyUsd: 2 });
|
||||
|
||||
return (
|
||||
<Tr>
|
||||
<Tr
|
||||
sx={{
|
||||
'&:hover [aria-label="Add token to wallet"]': {
|
||||
opacity: 1,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Td verticalAlign="middle">
|
||||
<TokenEntity
|
||||
token={ token }
|
||||
@@ -39,7 +45,7 @@ const ERC20TokensTableItem = ({
|
||||
isLoading={ isLoading }
|
||||
noIcon
|
||||
/>
|
||||
<AddressAddToWallet token={ token } ml={ 4 } isLoading={ isLoading }/>
|
||||
<AddressAddToWallet token={ token } ml={ 4 } isLoading={ isLoading } opacity="0"/>
|
||||
</Flex>
|
||||
</Td>
|
||||
<Td isNumeric verticalAlign="middle">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Box, Flex, Icon, Skeleton, Text, useColorModeValue } from '@chakra-ui/react';
|
||||
import { Box, Flex, Skeleton, Text, useColorModeValue } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import walletIcon from 'icons/wallet.svg';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
const TokenBalancesItem = ({ name, value, isLoading }: {name: string; value: string; isLoading: boolean }) => {
|
||||
|
||||
@@ -9,7 +9,7 @@ const TokenBalancesItem = ({ name, value, isLoading }: {name: string; value: str
|
||||
|
||||
return (
|
||||
<Flex p={ 5 } bgColor={ bgColor } borderRadius="16px" alignItems="center">
|
||||
<Icon as={ walletIcon } boxSize="30px" mr={ 3 }/>
|
||||
<IconSvg name="wallet" boxSize="30px" mr={ 3 }/>
|
||||
<Box>
|
||||
<Text variant="secondary" fontSize="xs">{ name }</Text>
|
||||
<Skeleton isLoaded={ !isLoading } fontWeight="500">{ value }</Skeleton>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Icon, Modal, ModalBody, ModalCloseButton, ModalContent, ModalHeader, ModalOverlay, Link } from '@chakra-ui/react';
|
||||
import { Modal, ModalBody, ModalCloseButton, ModalContent, ModalHeader, ModalOverlay, Link } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { AddressVerificationFormFirstStepFields, AddressCheckStatusSuccess } from './types';
|
||||
import type { VerifiedAddress } from 'types/api/account';
|
||||
|
||||
import eastArrowIcon from 'icons/arrows/east.svg';
|
||||
import * as mixpanel from 'lib/mixpanel/index';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import Web3ModalProvider from 'ui/shared/Web3ModalProvider';
|
||||
|
||||
import AddressVerificationStepAddress from './steps/AddressVerificationStepAddress';
|
||||
@@ -100,7 +100,7 @@ const AddressVerificationModal = ({ defaultAddress, isOpen, onClose, onSubmit, o
|
||||
<ModalHeader fontWeight="500" textStyle="h3" mb={ 6 }>
|
||||
{ stepIndex !== 0 && (
|
||||
<Link mr={ 3 } onClick={ handleGoToPrevStep }>
|
||||
<Icon as={ eastArrowIcon } boxSize={ 6 } transform="rotate(180deg)" verticalAlign="middle"/>
|
||||
<IconSvg name="arrows/east" boxSize={ 6 } transform="rotate(180deg)" verticalAlign="middle"/>
|
||||
</Link>
|
||||
) }
|
||||
<span>{ step.title }</span>
|
||||
|
||||
@@ -11,8 +11,6 @@ import type { Block } from 'types/api/block';
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import clockIcon from 'icons/clock.svg';
|
||||
import flameIcon from 'icons/flame.svg';
|
||||
import type { ResourceError } from 'lib/api/resources';
|
||||
import getBlockReward from 'lib/block/getBlockReward';
|
||||
import { GWEI, WEI, WEI_IN_GWEI, ZERO } from 'lib/consts';
|
||||
@@ -20,7 +18,6 @@ import dayjs from 'lib/date/dayjs';
|
||||
import { space } from 'lib/html-entities';
|
||||
import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle';
|
||||
import getQueryParamString from 'lib/router/getQueryParamString';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import CopyToClipboard from 'ui/shared/CopyToClipboard';
|
||||
import DataFetchAlert from 'ui/shared/DataFetchAlert';
|
||||
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
|
||||
@@ -28,6 +25,7 @@ import DetailsInfoItemDivider from 'ui/shared/DetailsInfoItemDivider';
|
||||
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
|
||||
import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio';
|
||||
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import PrevNext from 'ui/shared/PrevNext';
|
||||
import RawDataSnippet from 'ui/shared/RawDataSnippet';
|
||||
@@ -169,7 +167,7 @@ const BlockDetails = ({ query }: Props) => {
|
||||
hint="Date & time at which block was produced."
|
||||
isLoading={ isPlaceholderData }
|
||||
>
|
||||
<Icon as={ clockIcon } boxSize={ 5 } color="gray.500" isLoading={ isPlaceholderData }/>
|
||||
<IconSvg name="clock" boxSize={ 5 } color="gray.500" isLoading={ isPlaceholderData }/>
|
||||
<Skeleton isLoaded={ !isPlaceholderData } ml={ 1 }>
|
||||
{ dayjs(data.timestamp).fromNow() }
|
||||
</Skeleton>
|
||||
@@ -318,7 +316,7 @@ const BlockDetails = ({ query }: Props) => {
|
||||
}
|
||||
isLoading={ isPlaceholderData }
|
||||
>
|
||||
<Icon as={ flameIcon } boxSize={ 5 } color="gray.500" isLoading={ isPlaceholderData }/>
|
||||
<IconSvg name="flame" boxSize={ 5 } color="gray.500" isLoading={ isPlaceholderData }/>
|
||||
<Skeleton isLoaded={ !isPlaceholderData } ml={ 2 }>
|
||||
{ burntFees.dividedBy(WEI).toFixed() } { config.chain.currency.symbol }
|
||||
</Skeleton>
|
||||
|
||||
@@ -8,15 +8,14 @@ import type { Block } from 'types/api/block';
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import flameIcon from 'icons/flame.svg';
|
||||
import getBlockTotalReward from 'lib/block/getBlockTotalReward';
|
||||
import { WEI } from 'lib/consts';
|
||||
import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle';
|
||||
import BlockTimestamp from 'ui/blocks/BlockTimestamp';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
|
||||
import TextSeparator from 'ui/shared/TextSeparator';
|
||||
@@ -106,7 +105,7 @@ const BlocksListItem = ({ data, isLoading, enableTimeIncrement }: Props) => {
|
||||
<Text fontWeight={ 500 }>Burnt fees</Text>
|
||||
<Flex columnGap={ 4 } mt={ 2 }>
|
||||
<Flex>
|
||||
<Icon as={ flameIcon } boxSize={ 5 } color="gray.500" isLoading={ isLoading }/>
|
||||
<IconSvg name="flame" boxSize={ 5 } color="gray.500" isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } display="inline-block" color="text_secondary" ml={ 2 }>
|
||||
<span>{ burntFees.div(WEI).toFixed() }</span>
|
||||
</Skeleton>
|
||||
|
||||
@@ -8,14 +8,13 @@ import type { Block } from 'types/api/block';
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import flameIcon from 'icons/flame.svg';
|
||||
import getBlockTotalReward from 'lib/block/getBlockTotalReward';
|
||||
import { WEI } from 'lib/consts';
|
||||
import BlockTimestamp from 'ui/blocks/BlockTimestamp';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import TextSeparator from 'ui/shared/TextSeparator';
|
||||
import Utilization from 'ui/shared/Utilization/Utilization';
|
||||
@@ -116,7 +115,7 @@ const BlocksTableItem = ({ data, isLoading, enableTimeIncrement }: Props) => {
|
||||
{ !isRollup && !config.UI.views.block.hiddenFields?.burnt_fees && (
|
||||
<Td fontSize="sm">
|
||||
<Flex alignItems="center" columnGap={ 2 }>
|
||||
<Icon as={ flameIcon } boxSize={ 5 } color={ burntFeesIconColor } isLoading={ isLoading }/>
|
||||
<IconSvg name="flame" boxSize={ 5 } color={ burntFeesIconColor } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } display="inline-block">
|
||||
{ burntFees.dividedBy(WEI).toFixed(8) }
|
||||
</Skeleton>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { chakra, Checkbox, Code, Icon } from '@chakra-ui/react';
|
||||
import { chakra, Checkbox, Code } from '@chakra-ui/react';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import React from 'react';
|
||||
import type { ControllerRenderProps } from 'react-hook-form';
|
||||
@@ -7,10 +7,10 @@ import { useFormContext, Controller } from 'react-hook-form';
|
||||
import type { FormFields } from '../types';
|
||||
import type { SmartContractVerificationConfig } from 'types/api/contract';
|
||||
|
||||
import iconSearch from 'icons/search.svg';
|
||||
import { getResourceKey } from 'lib/api/useApiQuery';
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import FancySelect from 'ui/shared/FancySelect/FancySelect';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
import ContractVerificationFormRow from '../ContractVerificationFormRow';
|
||||
|
||||
@@ -56,7 +56,7 @@ const ContractVerificationFieldCompiler = ({ isVyper }: Props) => {
|
||||
defaultOptions
|
||||
size={ isMobile ? 'md' : 'lg' }
|
||||
placeholder="Compiler (enter version or use the dropdown)"
|
||||
placeholderIcon={ <Icon as={ iconSearch }/> }
|
||||
placeholderIcon={ <IconSvg name="search"/> }
|
||||
isDisabled={ formState.isSubmitting }
|
||||
error={ error }
|
||||
isRequired
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { Flex, FormControl, Icon, IconButton, Input, Text } from '@chakra-ui/react';
|
||||
import { Flex, FormControl, IconButton, Input, Text } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
import type { Control, ControllerRenderProps, FieldError } from 'react-hook-form';
|
||||
import { Controller } from 'react-hook-form';
|
||||
|
||||
import type { FormFields } from '../types';
|
||||
|
||||
import minusIcon from 'icons/minus.svg';
|
||||
import plusIcon from 'icons/plus.svg';
|
||||
import { ADDRESS_REGEXP } from 'lib/validations/address';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import InputPlaceholder from 'ui/shared/InputPlaceholder';
|
||||
|
||||
import ContractVerificationFormRow from '../ContractVerificationFormRow';
|
||||
@@ -86,7 +85,7 @@ const ContractVerificationFieldLibraryItem = ({ control, index, fieldsLength, on
|
||||
w="30px"
|
||||
h="30px"
|
||||
onClick={ handleRemoveButtonClick }
|
||||
icon={ <Icon as={ minusIcon } w="20px" h="20px"/> }
|
||||
icon={ <IconSvg name="minus" w="20px" h="20px"/> }
|
||||
isDisabled={ isDisabled }
|
||||
/>
|
||||
) }
|
||||
@@ -97,7 +96,7 @@ const ContractVerificationFieldLibraryItem = ({ control, index, fieldsLength, on
|
||||
w="30px"
|
||||
h="30px"
|
||||
onClick={ handleAddButtonClick }
|
||||
icon={ <Icon as={ plusIcon } w="20px" h="20px"/> }
|
||||
icon={ <IconSvg name="plus" w="20px" h="20px"/> }
|
||||
isDisabled={ isDisabled }
|
||||
/>
|
||||
) }
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {
|
||||
Link,
|
||||
Icon,
|
||||
chakra,
|
||||
Popover,
|
||||
PopoverTrigger,
|
||||
@@ -20,9 +19,9 @@ import { Controller } from 'react-hook-form';
|
||||
import type { FormFields } from '../types';
|
||||
import type { SmartContractVerificationConfig, SmartContractVerificationMethod } from 'types/api/contract';
|
||||
|
||||
import infoIcon from 'icons/info.svg';
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import FancySelect from 'ui/shared/FancySelect/FancySelect';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
import { METHOD_LABELS } from '../utils';
|
||||
|
||||
@@ -105,7 +104,7 @@ const ContractVerificationFieldMethod = ({ control, isDisabled, methods }: Props
|
||||
<Popover trigger="hover" isLazy placement={ isMobile ? 'bottom-end' : 'right-start' } offset={ [ -8, 8 ] }>
|
||||
<PopoverTrigger>
|
||||
<chakra.span display="inline-block" ml={ 1 } cursor="pointer" verticalAlign="middle" h="22px">
|
||||
<Icon as={ infoIcon } boxSize={ 5 } color="link" _hover={{ color: 'link_hovered' }}/>
|
||||
<IconSvg name="info" boxSize={ 5 } color="link" _hover={{ color: 'link_hovered' }}/>
|
||||
</chakra.span>
|
||||
</PopoverTrigger>
|
||||
<Portal>
|
||||
|
||||
@@ -11,12 +11,11 @@ import React from 'react';
|
||||
import type { Transaction } from 'types/api/transaction';
|
||||
|
||||
import config from 'configs/app';
|
||||
import rightArrowIcon from 'icons/arrows/east.svg';
|
||||
import getValueWithUnit from 'lib/getValueWithUnit';
|
||||
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import TxStatus from 'ui/shared/statusTag/TxStatus';
|
||||
import TxFeeStability from 'ui/shared/tx/TxFeeStability';
|
||||
import TxWatchListTags from 'ui/shared/tx/TxWatchListTags';
|
||||
@@ -78,8 +77,8 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
|
||||
</Box>
|
||||
</Flex>
|
||||
<Grid alignItems="center" alignSelf="flex-start" templateColumns="24px auto">
|
||||
<Icon
|
||||
as={ rightArrowIcon }
|
||||
<IconSvg
|
||||
name="arrows/east"
|
||||
boxSize={ 6 }
|
||||
color="gray.500"
|
||||
transform="rotate(90deg)"
|
||||
|
||||
@@ -10,12 +10,11 @@ import React from 'react';
|
||||
import type { Transaction } from 'types/api/transaction';
|
||||
|
||||
import config from 'configs/app';
|
||||
import rightArrowIcon from 'icons/arrows/east.svg';
|
||||
import getValueWithUnit from 'lib/getValueWithUnit';
|
||||
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import TxStatus from 'ui/shared/statusTag/TxStatus';
|
||||
import TxFeeStability from 'ui/shared/tx/TxFeeStability';
|
||||
import TxWatchListTags from 'ui/shared/tx/TxWatchListTags';
|
||||
@@ -76,8 +75,8 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
|
||||
fontWeight="500"
|
||||
mr={ 2 }
|
||||
/>
|
||||
<Icon
|
||||
as={ rightArrowIcon }
|
||||
<IconSvg
|
||||
name="arrows/east"
|
||||
boxSize={ 6 }
|
||||
color="gray.500"
|
||||
isLoading={ isLoading }
|
||||
|
||||
@@ -5,13 +5,6 @@ import React from 'react';
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import blockIcon from 'icons/block.svg';
|
||||
import clockIcon from 'icons/clock-light.svg';
|
||||
import bitcoinIcon from 'icons/coins/bitcoin.svg';
|
||||
import gasIcon from 'icons/gas.svg';
|
||||
import txIcon from 'icons/transactions.svg';
|
||||
import batchesIcon from 'icons/txn_batches.svg';
|
||||
import walletIcon from 'icons/wallet.svg';
|
||||
import useApiQuery from 'lib/api/useApiQuery';
|
||||
import { WEI } from 'lib/consts';
|
||||
import { HOMEPAGE_STATS } from 'stubs/stats';
|
||||
@@ -58,7 +51,7 @@ const Stats = () => {
|
||||
<>
|
||||
{ config.features.zkEvmRollup.isEnabled ? (
|
||||
<StatsItem
|
||||
icon={ batchesIcon }
|
||||
icon="txn_batches"
|
||||
title="Latest batch"
|
||||
value={ (zkEvmLatestBatchQuery.data || 0).toLocaleString() }
|
||||
url={ route({ pathname: '/zkevm-l2-txn-batches' }) }
|
||||
@@ -66,7 +59,7 @@ const Stats = () => {
|
||||
/>
|
||||
) : (
|
||||
<StatsItem
|
||||
icon={ blockIcon }
|
||||
icon="block"
|
||||
title="Total blocks"
|
||||
value={ Number(data.total_blocks).toLocaleString() }
|
||||
url={ route({ pathname: '/blocks' }) }
|
||||
@@ -75,21 +68,21 @@ const Stats = () => {
|
||||
) }
|
||||
{ hasAvgBlockTime && (
|
||||
<StatsItem
|
||||
icon={ clockIcon }
|
||||
icon="clock-light"
|
||||
title="Average block time"
|
||||
value={ `${ (data.average_block_time / 1000).toFixed(1) }s` }
|
||||
isLoading={ isPlaceholderData }
|
||||
/>
|
||||
) }
|
||||
<StatsItem
|
||||
icon={ txIcon }
|
||||
icon="transactions"
|
||||
title="Total transactions"
|
||||
value={ Number(data.total_transactions).toLocaleString() }
|
||||
url={ route({ pathname: '/txs' }) }
|
||||
isLoading={ isPlaceholderData }
|
||||
/>
|
||||
<StatsItem
|
||||
icon={ walletIcon }
|
||||
icon="wallet"
|
||||
title="Wallet addresses"
|
||||
value={ Number(data.total_addresses).toLocaleString() }
|
||||
_last={ isOdd ? lastItemTouchStyle : undefined }
|
||||
@@ -97,7 +90,7 @@ const Stats = () => {
|
||||
/>
|
||||
{ hasGasTracker && data.gas_prices && (
|
||||
<StatsItem
|
||||
icon={ gasIcon }
|
||||
icon="gas"
|
||||
title="Gas tracker"
|
||||
value={ `${ Number(data.gas_prices.average).toLocaleString() } Gwei` }
|
||||
_last={ isOdd ? lastItemTouchStyle : undefined }
|
||||
@@ -107,7 +100,7 @@ const Stats = () => {
|
||||
) }
|
||||
{ data.rootstock_locked_btc && (
|
||||
<StatsItem
|
||||
icon={ bitcoinIcon }
|
||||
icon="coins/bitcoin"
|
||||
title="BTC Locked in 2WP"
|
||||
value={ `${ BigNumber(data.rootstock_locked_btc).div(WEI).dp(0).toFormat() } RBTC` }
|
||||
_last={ isOdd ? lastItemTouchStyle : undefined }
|
||||
|
||||
@@ -3,11 +3,12 @@ import { Skeleton, Flex, useColorModeValue, chakra, LightMode } from '@chakra-ui
|
||||
import React from 'react';
|
||||
|
||||
import breakpoints from 'theme/foundations/breakpoints';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import Hint from 'ui/shared/Hint';
|
||||
import type { IconName } from 'ui/shared/IconSvg';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
type Props = {
|
||||
icon: React.FC<React.SVGAttributes<SVGElement>>;
|
||||
icon: IconName;
|
||||
title: string;
|
||||
value: string;
|
||||
className?: string;
|
||||
@@ -57,7 +58,7 @@ const StatsItem = ({ icon, title, value, className, tooltipLabel, url, isLoading
|
||||
href: url,
|
||||
} : {}) }
|
||||
>
|
||||
<Icon as={ icon } boxSize={ 7 } isLoading={ isLoading } borderRadius="base"/>
|
||||
<IconSvg name={ icon } boxSize={ 7 } isLoading={ isLoading } borderRadius="base"/>
|
||||
<Flex
|
||||
flexDirection="column"
|
||||
alignItems="start"
|
||||
|
||||
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -1,20 +1,17 @@
|
||||
import { Icon } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { TChainIndicator } from '../types';
|
||||
|
||||
import config from 'configs/app';
|
||||
import globeIcon from 'icons/globe.svg';
|
||||
import lockIcon from 'icons/lock.svg';
|
||||
import txIcon from 'icons/transactions.svg';
|
||||
import { sortByDateDesc } from 'ui/shared/chart/utils/sorts';
|
||||
import * as TokenEntity from 'ui/shared/entities/token/TokenEntity';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
const dailyTxsIndicator: TChainIndicator<'homepage_chart_txs'> = {
|
||||
id: 'daily_txs',
|
||||
title: 'Daily transactions',
|
||||
value: (stats) => Number(stats.transactions_today).toLocaleString(undefined, { maximumFractionDigits: 2, notation: 'compact' }),
|
||||
icon: <Icon as={ txIcon } 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.`,
|
||||
api: {
|
||||
resourceName: 'homepage_chart_txs',
|
||||
@@ -58,7 +55,7 @@ const marketPriceIndicator: TChainIndicator<'homepage_chart_market'> = {
|
||||
id: 'market_cap',
|
||||
title: 'Market cap',
|
||||
value: (stats) => '$' + Number(stats.market_cap).toLocaleString(undefined, { maximumFractionDigits: 0, notation: 'compact' }),
|
||||
icon: <Icon as={ globeIcon } 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
|
||||
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: {
|
||||
@@ -81,7 +78,7 @@ const tvlIndicator: TChainIndicator<'homepage_chart_market'> = {
|
||||
id: 'tvl',
|
||||
title: 'Total value locked',
|
||||
value: (stats) => '$' + Number(stats.tvl).toLocaleString(undefined, { maximumFractionDigits: 2, notation: 'compact' }),
|
||||
icon: <Icon as={ lockIcon } 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
|
||||
hint: 'Total value of digital assets locked or staked in a chain',
|
||||
api: {
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { Box, Icon, IconButton, Image, Link, LinkBox, Skeleton, useColorModeValue } from '@chakra-ui/react';
|
||||
import { Box, IconButton, Image, Link, LinkBox, Skeleton, useColorModeValue } from '@chakra-ui/react';
|
||||
import type { MouseEvent } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import type { MarketplaceAppPreview } from 'types/client/marketplace';
|
||||
|
||||
import northEastIcon from 'icons/arrows/north-east.svg';
|
||||
import starFilledIcon from 'icons/star_filled.svg';
|
||||
import starOutlineIcon from 'icons/star_outline.svg';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
import MarketplaceAppCardLink from './MarketplaceAppCardLink';
|
||||
|
||||
@@ -152,8 +150,8 @@ const MarketplaceAppCard = ({
|
||||
>
|
||||
More
|
||||
|
||||
<Icon
|
||||
as={ northEastIcon }
|
||||
<IconSvg
|
||||
name="arrows/north-east"
|
||||
marginLeft={ 1 }
|
||||
/>
|
||||
</Link>
|
||||
@@ -175,8 +173,8 @@ const MarketplaceAppCard = ({
|
||||
h={ 8 }
|
||||
onClick={ handleFavoriteClick }
|
||||
icon={ isFavorite ?
|
||||
<Icon as={ starFilledIcon } w={ 4 } h={ 4 } color="yellow.400"/> :
|
||||
<Icon as={ starOutlineIcon } w={ 4 } h={ 4 } color="gray.300"/>
|
||||
<IconSvg name="star_filled" w={ 4 } h={ 4 } color="yellow.400"/> :
|
||||
<IconSvg name="star_outline" w={ 4 } h={ 4 } color="gray.300"/>
|
||||
}
|
||||
/>
|
||||
) }
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
import {
|
||||
Box, Flex, Heading, Icon, IconButton, Image, Link, List, Modal, ModalBody,
|
||||
Box, Flex, Heading, IconButton, Image, Link, List, Modal, ModalBody,
|
||||
ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, Tag, Text, useColorModeValue,
|
||||
} from '@chakra-ui/react';
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import type { MarketplaceAppOverview } from 'types/client/marketplace';
|
||||
|
||||
import linkIcon from 'icons/link.svg';
|
||||
import ghIcon from 'icons/social/git.svg';
|
||||
import tgIcon from 'icons/social/telega.svg';
|
||||
import twIcon from 'icons/social/tweet.svg';
|
||||
import starFilledIcon from 'icons/star_filled.svg';
|
||||
import starOutlineIcon from 'icons/star_outline.svg';
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import { nbsp } from 'lib/html-entities';
|
||||
import type { IconName } from 'ui/shared/IconSvg';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
import MarketplaceAppModalLink from './MarketplaceAppModalLink';
|
||||
|
||||
@@ -47,15 +43,15 @@ const MarketplaceAppModal = ({
|
||||
|
||||
const socialLinks = [
|
||||
telegram ? {
|
||||
icon: tgIcon,
|
||||
icon: 'social/telega' as IconName,
|
||||
url: telegram,
|
||||
} : null,
|
||||
twitter ? {
|
||||
icon: twIcon,
|
||||
icon: 'social/tweet' as IconName,
|
||||
url: twitter,
|
||||
} : null,
|
||||
github ? {
|
||||
icon: ghIcon,
|
||||
icon: 'social/git' as IconName,
|
||||
url: github,
|
||||
} : null,
|
||||
].filter(Boolean);
|
||||
@@ -138,8 +134,8 @@ const MarketplaceAppModal = ({
|
||||
h={ 8 }
|
||||
onClick={ handleFavoriteClick }
|
||||
icon={ isFavorite ?
|
||||
<Icon as={ starFilledIcon } w={ 4 } h={ 4 } color="yellow.400"/> :
|
||||
<Icon as={ starOutlineIcon } w={ 4 } h={ 4 } color="gray.300"/> }
|
||||
<IconSvg name="star_filled" w={ 4 } h={ 4 } color="yellow.400"/> :
|
||||
<IconSvg name="star_outline" w={ 4 } h={ 4 } color="gray.300"/> }
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
@@ -188,8 +184,8 @@ const MarketplaceAppModal = ({
|
||||
maxW="100%"
|
||||
overflow="hidden"
|
||||
>
|
||||
<Icon
|
||||
as={ linkIcon }
|
||||
<IconSvg
|
||||
name="link"
|
||||
display="inline"
|
||||
verticalAlign="baseline"
|
||||
boxSize="18px"
|
||||
@@ -227,8 +223,8 @@ const MarketplaceAppModal = ({
|
||||
w={ 10 }
|
||||
h={ 10 }
|
||||
>
|
||||
<Icon
|
||||
as={ icon }
|
||||
<IconSvg
|
||||
name={ icon }
|
||||
w="20px"
|
||||
h="20px"
|
||||
display="block"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Box, Button, Icon, Menu, MenuButton, MenuList, Skeleton } from '@chakra-ui/react';
|
||||
import { Box, Button, Menu, MenuButton, MenuList, Skeleton } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import { MarketplaceCategory } from 'types/client/marketplace';
|
||||
|
||||
import eastMiniArrowIcon from 'icons/arrows/east-mini.svg';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
import MarketplaceCategoriesMenuItem from './MarketplaceCategoriesMenuItem';
|
||||
|
||||
@@ -50,7 +50,7 @@ const MarketplaceCategoriesMenu = ({ selectedCategoryId, onSelect, categories, i
|
||||
alignItems="center"
|
||||
>
|
||||
{ selectedCategoryId }
|
||||
<Icon transform="rotate(-90deg)" ml={{ base: 'auto', sm: 1 }} as={ eastMiniArrowIcon } w={ 5 } h={ 5 }/>
|
||||
<IconSvg transform="rotate(-90deg)" ml={{ base: 'auto', sm: 1 }} name="arrows/east-mini" w={ 5 } h={ 5 }/>
|
||||
</Box>
|
||||
</MenuButton>
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { Icon, MenuItem } from '@chakra-ui/react';
|
||||
import type { FunctionComponent, SVGAttributes } from 'react';
|
||||
import { MenuItem } from '@chakra-ui/react';
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import { MarketplaceCategory } from 'types/client/marketplace';
|
||||
|
||||
import starFilledIcon from 'icons/star_filled.svg';
|
||||
import type { IconName } from 'ui/shared/IconSvg';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
type Props = {
|
||||
id: string;
|
||||
onClick: (category: string) => void;
|
||||
}
|
||||
|
||||
const ICONS: Record<string, FunctionComponent<SVGAttributes<SVGElement>>> = {
|
||||
[MarketplaceCategory.FAVORITES]: starFilledIcon,
|
||||
const ICONS: Record<string, IconName> = {
|
||||
[MarketplaceCategory.FAVORITES]: 'star_filled',
|
||||
};
|
||||
|
||||
const MarketplaceCategoriesMenuItem = ({ id, onClick }: Props) => {
|
||||
@@ -27,7 +27,7 @@ const MarketplaceCategoriesMenuItem = ({ id, onClick }: Props) => {
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
>
|
||||
{ id in ICONS && <Icon mr={ 3 } as={ ICONS[id] } w={ 4 } h={ 4 } color="blackAlpha.800"/> }
|
||||
{ id in ICONS && <IconSvg mr={ 3 } name={ ICONS[id] } w={ 4 } h={ 4 } color="blackAlpha.800"/> }
|
||||
{ id }
|
||||
</MenuItem>
|
||||
);
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { Box, Flex, HStack, Icon } from '@chakra-ui/react';
|
||||
import { Box, Flex, HStack } from '@chakra-ui/react';
|
||||
import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
|
||||
import type { RoutedTab } from 'ui/shared/Tabs/types';
|
||||
|
||||
import config from 'configs/app';
|
||||
import iconSuccess from 'icons/status/success.svg';
|
||||
import useApiQuery from 'lib/api/useApiQuery';
|
||||
import { useAppContext } from 'lib/contexts/app';
|
||||
import useContractTabs from 'lib/hooks/useContractTabs';
|
||||
@@ -30,6 +29,7 @@ import TextAd from 'ui/shared/ad/TextAd';
|
||||
import AddressAddToWallet from 'ui/shared/address/AddressAddToWallet';
|
||||
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
|
||||
import EntityTags from 'ui/shared/EntityTags';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import NetworkExplorers from 'ui/shared/NetworkExplorers';
|
||||
import PageTitle from 'ui/shared/Page/PageTitle';
|
||||
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
|
||||
@@ -127,7 +127,7 @@ const AddressPageContent = () => {
|
||||
return (
|
||||
<>
|
||||
<span>Contract</span>
|
||||
<Icon as={ iconSuccess } boxSize="14px" color="green.500" ml={ 1 }/>
|
||||
<IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 }/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Flex, Icon, Tooltip } from '@chakra-ui/react';
|
||||
import { Box, Flex, Tooltip } from '@chakra-ui/react';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { useRouter } from 'next/router';
|
||||
import React, { useEffect } from 'react';
|
||||
@@ -9,8 +9,6 @@ import type { PaginationParams } from 'ui/shared/pagination/types';
|
||||
import type { RoutedTab } from 'ui/shared/Tabs/types';
|
||||
|
||||
import config from 'configs/app';
|
||||
import iconSuccess from 'icons/status/success.svg';
|
||||
import iconVerifiedToken from 'icons/verified_token.svg';
|
||||
import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery';
|
||||
import { useAppContext } from 'lib/contexts/app';
|
||||
import useContractTabs from 'lib/hooks/useContractTabs';
|
||||
@@ -30,6 +28,7 @@ import AddressAddToWallet from 'ui/shared/address/AddressAddToWallet';
|
||||
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
|
||||
import * as TokenEntity from 'ui/shared/entities/token/TokenEntity';
|
||||
import EntityTags from 'ui/shared/EntityTags';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import NetworkExplorers from 'ui/shared/NetworkExplorers';
|
||||
import PageTitle from 'ui/shared/Page/PageTitle';
|
||||
import Pagination from 'ui/shared/pagination/Pagination';
|
||||
@@ -189,7 +188,7 @@ const TokenPageContent = () => {
|
||||
return (
|
||||
<>
|
||||
<span>Contract</span>
|
||||
<Icon as={ iconSuccess } boxSize="14px" color="green.500" ml={ 1 }/>
|
||||
<IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 }/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -250,7 +249,7 @@ const TokenPageContent = () => {
|
||||
{ verifiedInfoQuery.data?.tokenAddress && (
|
||||
<Tooltip label={ `Information on this token has been verified by ${ config.chain.name }` }>
|
||||
<Box boxSize={ 6 }>
|
||||
<Icon as={ iconVerifiedToken } color="green.500" boxSize={ 6 } cursor="pointer"/>
|
||||
<IconSvg name="verified_token" color="green.500" boxSize={ 6 } cursor="pointer"/>
|
||||
</Box>
|
||||
</Tooltip>
|
||||
) }
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Box, Text, Button, Heading, Icon, chakra } from '@chakra-ui/react';
|
||||
import { Box, Text, Button, Heading, chakra } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import iconEmailSent from 'icons/email-sent.svg';
|
||||
import useApiFetch from 'lib/api/useApiFetch';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import getErrorObjPayload from 'lib/errors/getErrorObjPayload';
|
||||
import getErrorObjStatusCode from 'lib/errors/getErrorObjStatusCode';
|
||||
import useToast from 'lib/hooks/useToast';
|
||||
import * as mixpanel from 'lib/mixpanel/index';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
interface Props {
|
||||
email?: string; // TODO: obtain email from API
|
||||
@@ -77,7 +77,7 @@ const UnverifiedEmail = ({ email }: Props) => {
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Icon as={ iconEmailSent } width="180px" height="auto" mt="52px"/>
|
||||
<IconSvg name="email-sent" width="180px" height="auto" mt="52px"/>
|
||||
<Heading mt={ 6 } size="2xl">Verify your email address</Heading>
|
||||
<Text variant="secondary" mt={ 3 }>
|
||||
<span>Please confirm your email address to use the My Account feature. A confirmation email was sent to </span>
|
||||
|
||||
|
Before Width: | Height: | Size: 239 KiB After Width: | Height: | Size: 239 KiB |
|
Before Width: | Height: | Size: 270 KiB After Width: | Height: | Size: 270 KiB |
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 138 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
@@ -1,13 +1,12 @@
|
||||
import type { InputProps } from '@chakra-ui/react';
|
||||
import { IconButton, Icon, Flex } from '@chakra-ui/react';
|
||||
import { IconButton, Flex } from '@chakra-ui/react';
|
||||
import React, { useCallback } from 'react';
|
||||
import type { ControllerRenderProps, Control, FieldError } from 'react-hook-form';
|
||||
import { Controller } from 'react-hook-form';
|
||||
|
||||
import MinusIcon from 'icons/minus.svg';
|
||||
import PlusIcon from 'icons/plus.svg';
|
||||
import { ADDRESS_REGEXP } from 'lib/validations/address';
|
||||
import AddressInput from 'ui/shared/AddressInput';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
import type { Inputs } from './PublicTagsForm';
|
||||
|
||||
@@ -60,7 +59,7 @@ export default function PublicTagFormAction({ control, index, fieldsLength, erro
|
||||
w="30px"
|
||||
h="30px"
|
||||
onClick={ onRemoveFieldClick(index) }
|
||||
icon={ <Icon as={ MinusIcon } w="20px" h="20px"/> }
|
||||
icon={ <IconSvg name="minus" w="20px" h="20px"/> }
|
||||
/>
|
||||
) }
|
||||
{ index === fieldsLength - 1 && fieldsLength < MAX_INPUTS_NUM && (
|
||||
@@ -70,7 +69,7 @@ export default function PublicTagFormAction({ control, index, fieldsLength, erro
|
||||
w="30px"
|
||||
h="30px"
|
||||
onClick={ onAddFieldClick }
|
||||
icon={ <Icon as={ PlusIcon } w="20px" h="20px"/> }
|
||||
icon={ <IconSvg name="plus" w="20px" h="20px"/> }
|
||||
/>
|
||||
) }
|
||||
</Flex>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex, Grid, Icon, Image, Box, Text, Skeleton, useColorMode, Tag } from '@chakra-ui/react';
|
||||
import { Flex, Grid, Image, Box, Text, Skeleton, useColorMode, Tag } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
import xss from 'xss';
|
||||
|
||||
@@ -6,9 +6,6 @@ import type { SearchResultItem } from 'types/api/search';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import labelIcon from 'icons/publictags_slim.svg';
|
||||
import iconSuccess from 'icons/status/success.svg';
|
||||
import verifiedToken from 'icons/verified_token.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import highlightText from 'lib/highlightText';
|
||||
import * as mixpanel from 'lib/mixpanel/index';
|
||||
@@ -18,6 +15,7 @@ import * as BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import * as TokenEntity from 'ui/shared/entities/token/TokenEntity';
|
||||
import * as TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import LinkExternal from 'ui/shared/LinkExternal';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
|
||||
@@ -68,7 +66,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
|
||||
textOverflow="ellipsis"
|
||||
/>
|
||||
</LinkInternal>
|
||||
{ data.is_verified_via_admin_panel && <Icon as={ verifiedToken } boxSize={ 4 } ml={ 1 } color="green.500"/> }
|
||||
{ data.is_verified_via_admin_panel && <IconSvg name="verified_token" boxSize={ 4 } ml={ 1 } color="green.500"/> }
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
@@ -107,7 +105,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
|
||||
case 'label': {
|
||||
return (
|
||||
<Flex alignItems="center">
|
||||
<Icon as={ labelIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/>
|
||||
<IconSvg name="publictags_slim" boxSize={ 6 } mr={ 2 } color="gray.500"/>
|
||||
<LinkInternal
|
||||
href={ route({ pathname: '/address/[hash]', query: { hash: data.address } }) }
|
||||
fontWeight={ 700 }
|
||||
@@ -214,12 +212,12 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
|
||||
<Text whiteSpace="nowrap" overflow="hidden">
|
||||
<HashStringShortenDynamic hash={ data.address } isTooltipDisabled/>
|
||||
</Text>
|
||||
{ data.is_smart_contract_verified && <Icon as={ iconSuccess } color="green.500" ml={ 1 }/> }
|
||||
{ data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> }
|
||||
</Skeleton>
|
||||
<Text overflow="hidden" whiteSpace="nowrap" textOverflow="ellipsis" fontWeight={ 700 }>
|
||||
<Skeleton isLoaded={ !isLoading } overflow="hidden" whiteSpace="nowrap" textOverflow="ellipsis" fontWeight={ 700 }>
|
||||
{ data.token_type === 'ERC-20' && data.exchange_rate && `$${ Number(data.exchange_rate).toLocaleString() }` }
|
||||
{ data.token_type !== 'ERC-20' && data.total_supply && `Items ${ Number(data.total_supply).toLocaleString() }` }
|
||||
</Text>
|
||||
</Skeleton>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
@@ -245,7 +243,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
|
||||
<Box overflow="hidden">
|
||||
<HashStringShortenDynamic hash={ data.address }/>
|
||||
</Box>
|
||||
{ data.is_smart_contract_verified && <Icon as={ iconSuccess } color="green.500" ml={ 1 }/> }
|
||||
{ data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> }
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Tr, Td, Text, Flex, Icon, Image, Box, Skeleton, useColorMode, Tag } from '@chakra-ui/react';
|
||||
import { Tr, Td, Text, Flex, Image, Box, Skeleton, useColorMode, Tag } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
import xss from 'xss';
|
||||
|
||||
@@ -6,9 +6,6 @@ import type { SearchResultItem } from 'types/api/search';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import labelIcon from 'icons/publictags_slim.svg';
|
||||
import iconSuccess from 'icons/status/success.svg';
|
||||
import verifiedToken from 'icons/verified_token.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import highlightText from 'lib/highlightText';
|
||||
import * as mixpanel from 'lib/mixpanel/index';
|
||||
@@ -18,6 +15,7 @@ import * as BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import * as TokenEntity from 'ui/shared/entities/token/TokenEntity';
|
||||
import * as TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import LinkExternal from 'ui/shared/LinkExternal';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import type { SearchResultAppItem } from 'ui/shared/search/utils';
|
||||
@@ -68,7 +66,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
|
||||
dangerouslySetInnerHTML={{ __html: highlightText(name, searchTerm) }}
|
||||
/>
|
||||
</LinkInternal>
|
||||
{ data.is_verified_via_admin_panel && <Icon as={ verifiedToken } boxSize={ 4 } ml={ 1 } color="green.500"/> }
|
||||
{ data.is_verified_via_admin_panel && <IconSvg name="verified_token" boxSize={ 4 } ml={ 1 } color="green.500"/> }
|
||||
</Flex>
|
||||
</Td>
|
||||
<Td fontSize="sm" verticalAlign="middle">
|
||||
@@ -76,7 +74,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
|
||||
<Box overflow="hidden" whiteSpace="nowrap" w={ data.is_smart_contract_verified ? 'calc(100%-28px)' : 'unset' }>
|
||||
<HashStringShortenDynamic hash={ data.address }/>
|
||||
</Box>
|
||||
{ data.is_smart_contract_verified && <Icon as={ iconSuccess } color="green.500" ml={ 1 }/> }
|
||||
{ data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> }
|
||||
</Skeleton>
|
||||
</Td>
|
||||
<Td fontSize="sm" verticalAlign="middle" isNumeric>
|
||||
@@ -165,7 +163,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
|
||||
<>
|
||||
<Td fontSize="sm">
|
||||
<Flex alignItems="center">
|
||||
<Icon as={ labelIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/>
|
||||
<IconSvg name="publictags_slim" boxSize={ 6 } mr={ 2 } color="gray.500"/>
|
||||
<LinkInternal
|
||||
href={ route({ pathname: '/address/[hash]', query: { hash: data.address } }) }
|
||||
fontWeight={ 700 }
|
||||
@@ -182,7 +180,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
|
||||
<Box overflow="hidden" whiteSpace="nowrap" w={ data.is_smart_contract_verified ? 'calc(100%-28px)' : 'unset' }>
|
||||
<HashStringShortenDynamic hash={ data.address }/>
|
||||
</Box>
|
||||
{ data.is_smart_contract_verified && <Icon as={ iconSuccess } color="green.500" ml={ 1 }/> }
|
||||
{ data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> }
|
||||
</Flex>
|
||||
</Td>
|
||||
<Td></Td>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Button, Menu, MenuButton, MenuList, Icon, Flex, Skeleton, chakra } from '@chakra-ui/react';
|
||||
import { Button, Menu, MenuButton, MenuList, Flex, Skeleton, chakra } from '@chakra-ui/react';
|
||||
import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
|
||||
import config from 'configs/app';
|
||||
import iconArrow from 'icons/arrows/east-mini.svg';
|
||||
import useIsAccountActionAllowed from 'lib/hooks/useIsAccountActionAllowed';
|
||||
import * as mixpanel from 'lib/mixpanel/index';
|
||||
import getQueryParamString from 'lib/router/getQueryParamString';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
import PrivateTagMenuItem from './items/PrivateTagMenuItem';
|
||||
import PublicTagMenuItem from './items/PublicTagMenuItem';
|
||||
@@ -44,7 +44,7 @@ const AccountActionsMenu = ({ isLoading, className }: Props) => {
|
||||
>
|
||||
<Flex alignItems="center">
|
||||
<span>More</span>
|
||||
<Icon as={ iconArrow } transform="rotate(-90deg)" boxSize={ 5 } ml={ 1 }/>
|
||||
<IconSvg name="arrows/east-mini" transform="rotate(-90deg)" boxSize={ 5 } ml={ 1 }/>
|
||||
</Flex>
|
||||
</MenuButton>
|
||||
</Skeleton>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MenuItem, Icon, chakra, useDisclosure } from '@chakra-ui/react';
|
||||
import { MenuItem, chakra, useDisclosure } from '@chakra-ui/react';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
@@ -6,11 +6,11 @@ import React from 'react';
|
||||
import type { Address } from 'types/api/address';
|
||||
import type { Transaction } from 'types/api/transaction';
|
||||
|
||||
import iconPrivateTags from 'icons/privattags.svg';
|
||||
import { getResourceKey } from 'lib/api/useApiQuery';
|
||||
import getPageType from 'lib/mixpanel/getPageType';
|
||||
import AddressModal from 'ui/privateTags/AddressModal/AddressModal';
|
||||
import TransactionModal from 'ui/privateTags/TransactionModal/TransactionModal';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
@@ -61,7 +61,7 @@ const PrivateTagMenuItem = ({ className, hash, onBeforeClick, type = 'address' }
|
||||
return (
|
||||
<>
|
||||
<MenuItem className={ className } onClick={ handleClick }>
|
||||
<Icon as={ iconPrivateTags } boxSize={ 6 } mr={ 2 }/>
|
||||
<IconSvg name="privattags" boxSize={ 6 } mr={ 2 }/>
|
||||
<span>Add private tag</span>
|
||||
</MenuItem>
|
||||
{ type === 'tx' ?
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { MenuItem, Icon, chakra } from '@chakra-ui/react';
|
||||
import { MenuItem, chakra } from '@chakra-ui/react';
|
||||
import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
|
||||
import iconPublicTags from 'icons/publictags.svg';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
@@ -23,7 +23,7 @@ const PublicTagMenuItem = ({ className, hash, onBeforeClick }: Props) => {
|
||||
|
||||
return (
|
||||
<MenuItem className={ className }onClick={ handleClick }>
|
||||
<Icon as={ iconPublicTags } boxSize={ 6 } mr={ 2 }/>
|
||||
<IconSvg name="publictags" boxSize={ 6 } mr={ 2 }/>
|
||||
<span>Add public tag</span>
|
||||
</MenuItem>
|
||||
);
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { MenuItem, Icon, chakra, useDisclosure } from '@chakra-ui/react';
|
||||
import { MenuItem, chakra, useDisclosure } from '@chakra-ui/react';
|
||||
import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
|
||||
import type { Route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import iconEdit from 'icons/edit.svg';
|
||||
import useApiQuery from 'lib/api/useApiQuery';
|
||||
import useHasAccount from 'lib/hooks/useHasAccount';
|
||||
import { PAGE_TYPE_DICT } from 'lib/mixpanel/getPageType';
|
||||
import AddressVerificationModal from 'ui/addressVerification/AddressVerificationModal';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
@@ -61,7 +61,7 @@ const TokenInfoMenuItem = ({ className, hash, onBeforeClick }: Props) => {
|
||||
router.push({ pathname: '/account/verified-addresses' });
|
||||
}, [ router ]);
|
||||
|
||||
const icon = <Icon as={ iconEdit } boxSize={ 6 } mr={ 2 } p={ 1 }/>;
|
||||
const icon = <IconSvg name="edit" boxSize={ 6 } mr={ 2 } p={ 1 }/>;
|
||||
|
||||
const content = (() => {
|
||||
if (!verifiedAddressesQuery.data?.verifiedAddresses.find(({ contractAddress }) => contractAddress.toLowerCase() === hash.toLowerCase())) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {
|
||||
Icon,
|
||||
useColorModeValue,
|
||||
chakra,
|
||||
Button,
|
||||
@@ -7,7 +6,7 @@ import {
|
||||
} from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import infoIcon from 'icons/info.svg';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
interface Props {
|
||||
isOpen?: boolean;
|
||||
@@ -39,8 +38,8 @@ const AdditionalInfoButton = ({ isOpen, onClick, className, isLoading }: Props,
|
||||
cursor="pointer"
|
||||
flexShrink={ 0 }
|
||||
>
|
||||
<Icon
|
||||
as={ infoIcon }
|
||||
<IconSvg
|
||||
name="info"
|
||||
boxSize={ 5 }
|
||||
color="link"
|
||||
_hover={{ color: 'link_hovered' }}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { Box, HStack, Flex, Skeleton, useColorModeValue } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import keyIcon from 'icons/key.svg';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import CopyToClipboard from 'ui/shared/CopyToClipboard';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
interface Props {
|
||||
apiKey: string;
|
||||
@@ -14,7 +13,7 @@ interface Props {
|
||||
const ApiKeySnippet = ({ apiKey, name, isLoading }: Props) => {
|
||||
return (
|
||||
<HStack spacing={ 2 } alignItems="start">
|
||||
<Icon as={ keyIcon } boxSize={ 6 } color={ useColorModeValue('gray.500', 'gray.400') } isLoading={ isLoading }/>
|
||||
<IconSvg name="key" boxSize={ 6 } color={ useColorModeValue('gray.500', 'gray.400') } isLoading={ isLoading }/>
|
||||
<Box>
|
||||
<Flex alignItems={{ base: 'flex-start', lg: 'center' }}>
|
||||
<Skeleton isLoaded={ !isLoading } display="inline-block" fontWeight={ 600 } mr={ 1 }>
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
import { Icon } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import icon404 from 'icons/error-pages/404.svg';
|
||||
import icon422 from 'icons/error-pages/422.svg';
|
||||
import icon429 from 'icons/error-pages/429.svg';
|
||||
import icon500 from 'icons/error-pages/500.svg';
|
||||
import type { IconName } from 'ui/shared/IconSvg';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
const ICONS: Record<string, React.FunctionComponent<React.SVGAttributes<SVGElement>> > = {
|
||||
'404': icon404,
|
||||
'422': icon422,
|
||||
'429': icon429,
|
||||
'500': icon500,
|
||||
const ICONS: Record<string, IconName> = {
|
||||
'404': 'error-pages/404',
|
||||
'422': 'error-pages/422',
|
||||
'429': 'error-pages/429',
|
||||
'500': 'error-pages/500',
|
||||
};
|
||||
|
||||
interface Props {
|
||||
@@ -18,7 +15,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const AppErrorIcon = ({ statusCode }: Props) => {
|
||||
return <Icon as={ ICONS[String(statusCode)] || ICONS['500'] } width="200px" height="auto" color="text"/>;
|
||||
return <IconSvg name={ ICONS[String(statusCode)] || ICONS['500'] } width="200px" height="100px" color="text"/>;
|
||||
};
|
||||
|
||||
export default AppErrorIcon;
|
||||
|
||||
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
@@ -1,8 +1,8 @@
|
||||
/* eslint-disable max-len */
|
||||
import { Box, OrderedList, ListItem, Icon, useColorModeValue, Flex } from '@chakra-ui/react';
|
||||
import { Box, OrderedList, ListItem, useColorModeValue, Flex } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import txIcon from 'icons/transactions.svg';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
import AppErrorTitle from '../AppErrorTitle';
|
||||
|
||||
@@ -18,7 +18,7 @@ const AppErrorInvalidTxHash = () => {
|
||||
<>
|
||||
<Box p={ 4 } borderColor={ snippet.borderColor } borderRadius="md" w="230px" borderWidth="1px">
|
||||
<Flex alignItems="center" pb={ 4 } borderBottomWidth="1px" borderColor={ snippet.borderColor }>
|
||||
<Icon as={ txIcon } boxSize={ 8 } color={ snippet.iconColor } bgColor={ snippet.iconBg } p={ 1 } borderRadius="md"/>
|
||||
<IconSvg name="transactions" boxSize={ 8 } color={ snippet.iconColor } bgColor={ snippet.iconBg } p={ 1 } borderRadius="md"/>
|
||||
<Box ml={ 2 }>
|
||||
<Box w="125px" h="8px" borderRadius="full" bgColor={ snippet.iconBg }/>
|
||||
<Box w="30px" h="8px" borderRadius="full" bgColor={ snippet.borderColor } mt={ 1.5 }/>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { chakra, Icon, IconButton, useColorModeValue } from '@chakra-ui/react';
|
||||
import { chakra, IconButton, useColorModeValue } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import errorIcon from 'icons/status/error.svg';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
interface Props {
|
||||
onClick: (e: React.SyntheticEvent) => void;
|
||||
@@ -21,7 +21,7 @@ const ClearButton = ({ onClick, isDisabled, className }: Props) => {
|
||||
aria-label="Clear input"
|
||||
title="Clear input"
|
||||
boxSize={ 6 }
|
||||
icon={ <Icon as={ errorIcon } boxSize={ 3 } color={ iconColor } focusable={ false } _hover={{ color: iconColorHover }}/> }
|
||||
icon={ <IconSvg name="status/error" boxSize={ 3 } color={ iconColor } _hover={{ color: iconColorHover }}/> }
|
||||
size="sm"
|
||||
onClick={ onClick }
|
||||
/>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { IconButton, Tooltip, useClipboard, chakra, useDisclosure, Skeleton } from '@chakra-ui/react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import CopyIcon from 'icons/copy.svg';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
export interface Props {
|
||||
text: string;
|
||||
@@ -31,7 +31,7 @@ const CopyToClipboard = ({ text, className, isLoading }: Props) => {
|
||||
<Tooltip label={ copied ? 'Copied' : 'Copy to clipboard' } isOpen={ isOpen || copied }>
|
||||
<IconButton
|
||||
aria-label="copy"
|
||||
icon={ <CopyIcon/> }
|
||||
icon={ <IconSvg name="copy" boxSize={ 5 }/> }
|
||||
w="20px"
|
||||
h="20px"
|
||||
color="gray.400"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Box, Heading, Icon, Text } from '@chakra-ui/react';
|
||||
import { Box, Heading, Text } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import emptyIcon from 'icons/empty_search_result.svg';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
interface Props {
|
||||
text: string;
|
||||
@@ -14,8 +14,8 @@ const EmptySearchResult = ({ text }: Props) => {
|
||||
flexDirection="column"
|
||||
alignItems="center"
|
||||
>
|
||||
<Icon
|
||||
as={ emptyIcon }
|
||||
<IconSvg
|
||||
name="empty_search_result"
|
||||
boxSize={ 60 }
|
||||
display="block"
|
||||
/>
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { TooltipProps } from '@chakra-ui/react';
|
||||
import { chakra, IconButton, Tooltip, useDisclosure, Skeleton } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import InfoIcon from 'icons/info.svg';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
interface Props {
|
||||
label: string | React.ReactNode;
|
||||
@@ -21,7 +21,7 @@ const Hint = ({ label, className, tooltipProps, isLoading }: Props) => {
|
||||
}, [ onToggle ]);
|
||||
|
||||
if (isLoading) {
|
||||
return <Skeleton boxSize={ 5 } borderRadius="sm"/>;
|
||||
return <Skeleton className={ className } boxSize={ 5 } borderRadius="sm"/>;
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -35,7 +35,7 @@ const Hint = ({ label, className, tooltipProps, isLoading }: Props) => {
|
||||
<IconButton
|
||||
colorScheme="none"
|
||||
aria-label="hint"
|
||||
icon={ <InfoIcon/> }
|
||||
icon={ <IconSvg name="info" w="100%" h="100%"/> }
|
||||
boxSize={ 5 }
|
||||
variant="simple"
|
||||
display="inline-block"
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import type { HTMLChakraProps } from '@chakra-ui/react';
|
||||
import { Skeleton, chakra } from '@chakra-ui/react';
|
||||
import { type IconName } from 'public/icons/name';
|
||||
import React from 'react';
|
||||
|
||||
export const href = '/icons/sprite.svg';
|
||||
|
||||
export { IconName };
|
||||
|
||||
interface Props extends HTMLChakraProps<'div'> {
|
||||
name: IconName;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
const IconSvg = ({ name, isLoading, ...props }: Props) => {
|
||||
return (
|
||||
<Skeleton isLoaded={ !isLoading } display="inline-block" { ...props }>
|
||||
<chakra.svg w="100%" h="100%">
|
||||
<use href={ `${ href }#${ name }` }/>
|
||||
</chakra.svg>
|
||||
</Skeleton>
|
||||
);
|
||||
};
|
||||
|
||||
export default IconSvg;
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { ChakraProps } from '@chakra-ui/react';
|
||||
import { Link, Icon, chakra, Box, Skeleton, useColorModeValue } from '@chakra-ui/react';
|
||||
import { Link, chakra, Box, Skeleton, useColorModeValue } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import arrowIcon from 'icons/arrows/north-east.svg';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
interface Props {
|
||||
href: string;
|
||||
@@ -59,7 +59,7 @@ const LinkExternal = ({ href, children, className, isLoading, variant }: Props)
|
||||
return (
|
||||
<Link className={ className } { ...styleProps } target="_blank" href={ href }>
|
||||
{ children }
|
||||
<Icon as={ arrowIcon } boxSize={ 4 } verticalAlign="middle" color="gray.400"/>
|
||||
<IconSvg name="arrows/north-east" boxSize={ 4 } verticalAlign="middle" color="gray.400" flexShrink={ 0 }/>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button, Icon } from '@chakra-ui/react';
|
||||
import { Button } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import config from 'configs/app';
|
||||
@@ -7,6 +7,7 @@ import * as mixpanel from 'lib/mixpanel/index';
|
||||
import useAddOrSwitchChain from 'lib/web3/useAddOrSwitchChain';
|
||||
import useProvider from 'lib/web3/useProvider';
|
||||
import { WALLETS_INFO } from 'lib/web3/wallets';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
const feature = config.features.web3Wallet;
|
||||
|
||||
@@ -55,7 +56,7 @@ const NetworkAddToWallet = () => {
|
||||
|
||||
return (
|
||||
<Button variant="outline" size="sm" onClick={ handleClick }>
|
||||
<Icon as={ WALLETS_INFO[wallet].icon } boxSize={ 5 } mr={ 2 }/>
|
||||
<IconSvg name={ WALLETS_INFO[wallet].icon } boxSize={ 5 } mr={ 2 }/>
|
||||
Add { config.chain.name }
|
||||
</Button>
|
||||
);
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { Flex, Button, Icon, chakra, Popover, PopoverTrigger, PopoverBody, PopoverContent, useDisclosure } from '@chakra-ui/react';
|
||||
import { Flex, Button, chakra, Popover, PopoverTrigger, PopoverBody, PopoverContent, useDisclosure } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { NetworkExplorer as TNetworkExplorer } from 'types/networks';
|
||||
|
||||
import config from 'configs/app';
|
||||
import arrowIcon from 'icons/arrows/east-mini.svg';
|
||||
import explorerIcon from 'icons/explorer.svg';
|
||||
import stripTrailingSlash from 'lib/stripTrailingSlash';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import LinkExternal from 'ui/shared/LinkExternal';
|
||||
|
||||
interface Props {
|
||||
@@ -46,8 +45,8 @@ const NetworkExplorers = ({ className, type, pathParam }: Props) => {
|
||||
h="32px"
|
||||
flexShrink={ 0 }
|
||||
>
|
||||
<Icon as={ explorerIcon } boxSize={ 5 }/>
|
||||
<Icon as={ arrowIcon } transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } transitionDuration="faster" boxSize={ 5 }/>
|
||||
<IconSvg name="explorer" boxSize={ 5 }/>
|
||||
<IconSvg name="arrows/east-mini" transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } transitionDuration="faster" boxSize={ 5 }/>
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent w="240px">
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Heading, Flex, Tooltip, Icon, Link, chakra, Skeleton, useDisclosure } from '@chakra-ui/react';
|
||||
import { Heading, Flex, Tooltip, Link, chakra, Skeleton, useDisclosure } from '@chakra-ui/react';
|
||||
import _debounce from 'lodash/debounce';
|
||||
import React from 'react';
|
||||
|
||||
import eastArrowIcon from 'icons/arrows/east.svg';
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import TextAd from 'ui/shared/ad/TextAd';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
|
||||
type BackLinkProp = { label: string; url: string } | { label: string; onClick: () => void };
|
||||
@@ -32,7 +32,7 @@ const BackLink = (props: BackLinkProp & { isLoading?: boolean }) => {
|
||||
return <Skeleton boxSize={ 6 } display="inline-block" borderRadius="base" mr={ 3 } my={ 2 } verticalAlign="text-bottom" isLoaded={ !props.isLoading }/>;
|
||||
}
|
||||
|
||||
const icon = <Icon as={ eastArrowIcon } boxSize={ 6 } transform="rotate(180deg)" margin="auto" color="gray.400"/>;
|
||||
const icon = <IconSvg name="arrows/east" boxSize={ 6 } transform="rotate(180deg)" margin="auto" color="gray.400"/>;
|
||||
|
||||
if ('url' in props) {
|
||||
return (
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { Icon } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { TokenInfo } from 'types/api/token';
|
||||
|
||||
import iconVerifiedToken from 'icons/verified_token.svg';
|
||||
import * as addressMock from 'mocks/address/address';
|
||||
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
|
||||
import * as TokenEntity from 'ui/shared/entities/token/TokenEntity';
|
||||
import EntityTags from 'ui/shared/EntityTags';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import NetworkExplorers from 'ui/shared/NetworkExplorers';
|
||||
|
||||
import PageTitle from '../PageTitle';
|
||||
@@ -33,7 +32,7 @@ const DefaultView = () => {
|
||||
|
||||
const contentAfter = (
|
||||
<>
|
||||
<Icon as={ iconVerifiedToken } color="green.500" boxSize={ 6 } cursor="pointer"/>
|
||||
<IconSvg name="verified_token" color="green.500" boxSize={ 6 } cursor="pointer"/>
|
||||
<EntityTags
|
||||
tagsBefore={ [
|
||||
{ label: 'example', display_name: 'Example label' },
|
||||
|
||||