Commit f6f63b74 authored by tom's avatar tom

Merge branch 'main' of github.com:blockscout/frontend into feat/mixpanel

parents 798c3bed ee02cfae
...@@ -32,13 +32,14 @@ NEXT_PUBLIC_FOOTER_TELEGRAM_LINK=__PLACEHOLDER_FOR_NEXT_PUBLIC_FOOTER_TELEGRAM_L ...@@ -32,13 +32,14 @@ NEXT_PUBLIC_FOOTER_TELEGRAM_LINK=__PLACEHOLDER_FOR_NEXT_PUBLIC_FOOTER_TELEGRAM_L
NEXT_PUBLIC_FOOTER_STAKING_LINK=__PLACEHOLDER_FOR_NEXT_PUBLIC_FOOTER_STAKING_LINK__ NEXT_PUBLIC_FOOTER_STAKING_LINK=__PLACEHOLDER_FOR_NEXT_PUBLIC_FOOTER_STAKING_LINK__
NEXT_PUBLIC_FEATURED_NETWORKS=__PLACEHOLDER_FOR_NEXT_PUBLIC_FEATURED_NETWORKS__ NEXT_PUBLIC_FEATURED_NETWORKS=__PLACEHOLDER_FOR_NEXT_PUBLIC_FEATURED_NETWORKS__
NEXT_PUBLIC_NETWORK_EXPLORERS=__PLACEHOLDER_FOR_NEXT_PUBLIC_NETWORK_EXPLORERS__ NEXT_PUBLIC_NETWORK_EXPLORERS=__PLACEHOLDER_FOR_NEXT_PUBLIC_NETWORK_EXPLORERS__
NEXT_PUBLIC_OTHER_LINKS=__PLACEHOLDER_FOR_NEXT_PUBLIC_OTHER_LINKS__
NEXT_PUBLIC_MARKETPLACE_CONFIG_URL=__PLACEHOLDER_FOR_NEXT_PUBLIC_MARKETPLACE_CONFIG_URL__ NEXT_PUBLIC_MARKETPLACE_CONFIG_URL=__PLACEHOLDER_FOR_NEXT_PUBLIC_MARKETPLACE_CONFIG_URL__
NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=__PLACEHOLDER_FOR_NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM__ NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=__PLACEHOLDER_FOR_NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM__
NEXT_PUBLIC_LOGOUT_URL=__PLACEHOLDER_FOR_NEXT_PUBLIC_LOGOUT_URL__ NEXT_PUBLIC_LOGOUT_URL=__PLACEHOLDER_FOR_NEXT_PUBLIC_LOGOUT_URL__
NEXT_PUBLIC_LOGOUT_RETURN_URL=__PLACEHOLDER_FOR_NEXT_PUBLIC_LOGOUT_RETURN_URL__ NEXT_PUBLIC_LOGOUT_RETURN_URL=__PLACEHOLDER_FOR_NEXT_PUBLIC_LOGOUT_RETURN_URL__
NEXT_PUBLIC_HOMEPAGE_CHARTS=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_CHARTS__ NEXT_PUBLIC_HOMEPAGE_CHARTS=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_CHARTS__
NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR__ NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR__
NEXT_PUBLIC_HOMEPAGE_PLATE_GRADIENT=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_PLATE_GRADIENT__ NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND__
NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER__ NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER__
NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME__ NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME__
NEXT_PUBLIC_AD_DOMAIN_WITH_AD=__PLACEHOLDER_FOR_NEXT_PUBLIC_AD_DOMAIN_WITH_AD__ NEXT_PUBLIC_AD_DOMAIN_WITH_AD=__PLACEHOLDER_FOR_NEXT_PUBLIC_AD_DOMAIN_WITH_AD__
...@@ -55,6 +56,8 @@ NEXT_PUBLIC_API_PORT=__PLACEHOLDER_FOR_NEXT_PUBLIC_API_PORT__ ...@@ -55,6 +56,8 @@ NEXT_PUBLIC_API_PORT=__PLACEHOLDER_FOR_NEXT_PUBLIC_API_PORT__
NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=__PLACEHOLDER_FOR_NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL__ NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=__PLACEHOLDER_FOR_NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL__
NEXT_PUBLIC_STATS_API_HOST=__PLACEHOLDER_FOR_NEXT_PUBLIC_STATS_API_HOST__ NEXT_PUBLIC_STATS_API_HOST=__PLACEHOLDER_FOR_NEXT_PUBLIC_STATS_API_HOST__
NEXT_PUBLIC_VISUALIZE_API_HOST=__PLACEHOLDER_FOR_NEXT_PUBLIC_VISUALIZE_API_HOST__ NEXT_PUBLIC_VISUALIZE_API_HOST=__PLACEHOLDER_FOR_NEXT_PUBLIC_VISUALIZE_API_HOST__
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=__PLACEHOLDER_FOR_NEXT_PUBLIC_CONTRACT_INFO_API_HOST__
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=__PLACEHOLDER_FOR_NEXT_PUBLIC_ADMIN_SERVICE_API_HOST__
NEXT_PUBLIC_API_SPEC_URL=__PLACEHOLDER_FOR_NEXT_PUBLIC_API_SPEC_URL__ NEXT_PUBLIC_API_SPEC_URL=__PLACEHOLDER_FOR_NEXT_PUBLIC_API_SPEC_URL__
# external services config # external services config
......
name: Checks name: Checks
on: on:
workflow_dispatch:
pull_request: pull_request:
push: push:
branches: branches:
...@@ -9,6 +10,7 @@ jobs: ...@@ -9,6 +10,7 @@ jobs:
lint: lint:
name: ESLint name: ESLint
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: "!contains(github.event.pull_request.labels.*.name, 'WIP')"
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@v3 uses: actions/checkout@v3
...@@ -30,6 +32,7 @@ jobs: ...@@ -30,6 +32,7 @@ jobs:
type_check: type_check:
name: TypeScript name: TypeScript
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: "!contains(github.event.pull_request.labels.*.name, 'WIP')"
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@v3 uses: actions/checkout@v3
......
{
"typescript.tsdk": "node_modules/typescript/lib"
}
\ No newline at end of file
/* eslint-disable no-restricted-properties */ /* eslint-disable no-restricted-properties */
import type { NavItemExternal } from 'types/client/navigation-items';
import type { WalletType } from 'types/client/wallets'; import type { WalletType } from 'types/client/wallets';
import type { NetworkExplorer } from 'types/networks'; import type { NetworkExplorer } from 'types/networks';
import type { ChainIndicatorId } from 'ui/home/indicators/types'; import type { ChainIndicatorId } from 'ui/home/indicators/types';
...@@ -11,6 +12,7 @@ const parseEnvJson = <DataType>(env: string | undefined): DataType | null => { ...@@ -11,6 +12,7 @@ const parseEnvJson = <DataType>(env: string | undefined): DataType | null => {
return null; return null;
} }
}; };
const stripTrailingSlash = (str: string) => str[str.length - 1] === '/' ? str.slice(0, -1) : str; const stripTrailingSlash = (str: string) => str[str.length - 1] === '/' ? str.slice(0, -1) : str;
const getWeb3DefaultWallet = (): WalletType => { const getWeb3DefaultWallet = (): WalletType => {
const envValue = getEnvValue(process.env.NEXT_PUBLIC_WEB3_DEFAULT_WALLET); const envValue = getEnvValue(process.env.NEXT_PUBLIC_WEB3_DEFAULT_WALLET);
...@@ -100,6 +102,7 @@ const config = Object.freeze({ ...@@ -100,6 +102,7 @@ const config = Object.freeze({
telegram: getEnvValue(process.env.NEXT_PUBLIC_FOOTER_TELEGRAM_LINK), telegram: getEnvValue(process.env.NEXT_PUBLIC_FOOTER_TELEGRAM_LINK),
staking: getEnvValue(process.env.NEXT_PUBLIC_FOOTER_STAKING_LINK), staking: getEnvValue(process.env.NEXT_PUBLIC_FOOTER_STAKING_LINK),
}, },
otherLinks: parseEnvJson<Array<NavItemExternal>>(getEnvValue(process.env.NEXT_PUBLIC_OTHER_LINKS)) || [],
featuredNetworks: getEnvValue(process.env.NEXT_PUBLIC_FEATURED_NETWORKS), featuredNetworks: getEnvValue(process.env.NEXT_PUBLIC_FEATURED_NETWORKS),
blockScoutVersion: getEnvValue(process.env.NEXT_PUBLIC_BLOCKSCOUT_VERSION), blockScoutVersion: getEnvValue(process.env.NEXT_PUBLIC_BLOCKSCOUT_VERSION),
isAccountSupported: getEnvValue(process.env.NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED) === 'true', isAccountSupported: getEnvValue(process.env.NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED) === 'true',
...@@ -141,11 +144,19 @@ const config = Object.freeze({ ...@@ -141,11 +144,19 @@ const config = Object.freeze({
endpoint: getEnvValue(process.env.NEXT_PUBLIC_VISUALIZE_API_HOST), endpoint: getEnvValue(process.env.NEXT_PUBLIC_VISUALIZE_API_HOST),
basePath: '', basePath: '',
}, },
contractInfoApi: {
endpoint: getEnvValue(process.env.NEXT_PUBLIC_CONTRACT_INFO_API_HOST),
basePath: '',
},
adminServiceApi: {
endpoint: getEnvValue(process.env.NEXT_PUBLIC_ADMIN_SERVICE_API_HOST),
basePath: '',
},
homepage: { homepage: {
charts: parseEnvJson<Array<ChainIndicatorId>>(getEnvValue(process.env.NEXT_PUBLIC_HOMEPAGE_CHARTS)) || [], charts: parseEnvJson<Array<ChainIndicatorId>>(getEnvValue(process.env.NEXT_PUBLIC_HOMEPAGE_CHARTS)) || [],
plate: { plate: {
gradient: getEnvValue(process.env.NEXT_PUBLIC_HOMEPAGE_PLATE_GRADIENT) || background: getEnvValue(process.env.NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND) ||
'radial-gradient(103.03% 103.03% at 0% 0%, rgba(183, 148, 244, 0.8) 0%, rgba(0, 163, 196, 0.8) 100%)', 'radial-gradient(103.03% 103.03% at 0% 0%, rgba(183, 148, 244, 0.8) 0%, rgba(0, 163, 196, 0.8) 100%), var(--chakra-colors-blue-400)',
textColor: getEnvValue(process.env.NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR) || 'white', textColor: getEnvValue(process.env.NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR) || 'white',
}, },
showGasTracker: getEnvValue(process.env.NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER) === 'false' ? false : true, showGasTracker: getEnvValue(process.env.NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER) === 'false' ? false : true,
......
...@@ -13,5 +13,7 @@ NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout ...@@ -13,5 +13,7 @@ NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout
# api config # api config
NEXT_PUBLIC_API_HOST=blockscout.com NEXT_PUBLIC_API_HOST=blockscout.com
NEXT_PUBLIC_STATS_API_HOST=https://stats-test.aws-k8s.blockscout.com NEXT_PUBLIC_STATS_API_HOST=https://stats-test.k8s-dev.blockscout.com
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.aws-k8s.blockscout.com NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.k8s-dev.blockscout.com
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info-test.k8s-dev.blockscout.com
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs-test.k8s-dev.blockscout.com
# ui config # ui config
NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/eth-goerli.json NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/eth-goerli.json
NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Anyblock','baseUrl':'https://explorer.anyblock.tools','paths':{'tx':'/ethereum/ethereum/goerli/transaction','address':'/ethereum/ethereum/goerli/address'}},{'title':'Etherscan','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address'}}] NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Bitquery','baseUrl':'https://explorer.bitquery.io/','paths':{'tx':'/goerli/tx','address':'/goerli/address','token':'/goerli/token','block':'/goerli/block'}},{'title':'Etherscan','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}]
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d
# network config # network config
......
# ui config # ui config
NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/base-goerli.json NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/base-goerli.json
NEXT_PUBLIC_NETWORK_EXPLORERS= NEXT_PUBLIC_NETWORK_EXPLORERS=
NEXT_PUBLIC_HOMEPAGE_PLATE_GRADIENT=linear-gradient(136.9deg,rgb(107 94 236) 1.5%,rgb(0 82 255) 56.84%,rgb(82 62 231) 98.54%) NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND=linear-gradient(136.9deg,rgb(107 94 236) 1.5%,rgb(0 82 255) 56.84%,rgb(82 62 231) 98.54%)
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x4a0ed8ddf751a7cb5297f827699117b0f6d21a0b2907594d300dc9fed75c7e62 NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x4a0ed8ddf751a7cb5297f827699117b0f6d21a0b2907594d300dc9fed75c7e62
NEXT_PUBLIC_WEB3_DEFAULT_WALLET=coinbase NEXT_PUBLIC_WEB3_DEFAULT_WALLET=coinbase
NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET=true NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET=true
......
...@@ -13,7 +13,7 @@ NEXT_PUBLIC_FOOTER_GITHUB_LINK=https://github.com/blockscout/blockscout ...@@ -13,7 +13,7 @@ NEXT_PUBLIC_FOOTER_GITHUB_LINK=https://github.com/blockscout/blockscout
NEXT_PUBLIC_FOOTER_TWITTER_LINK=https://www.twitter.com/blockscoutcom NEXT_PUBLIC_FOOTER_TWITTER_LINK=https://www.twitter.com/blockscoutcom
NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/eth-goerli.json NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/eth-goerli.json
NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Anyblock','baseUrl':'https://explorer.anyblock.tools','paths':{'tx':'/ethereum/poa/core/transaction','address':'/ethereum/poa/core/address'}}] NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Anyblock','baseUrl':'https://explorer.anyblock.tools','paths':{'tx':'/ethereum/poa/core/transaction','address':'/ethereum/poa/core/address'}}]
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs','coin_price','market_cup'] NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs','coin_price','market_cap']
NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
# network config # network config
......
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
NEXT_PUBLIC_FOOTER_TELEGRAM_LINK=https://t.me/poa_network NEXT_PUBLIC_FOOTER_TELEGRAM_LINK=https://t.me/poa_network
NEXT_PUBLIC_FOOTER_STAKING_LINK=https://duneanalytics.com/maxaleks/xdai-staking NEXT_PUBLIC_FOOTER_STAKING_LINK=https://duneanalytics.com/maxaleks/xdai-staking
NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/eth-goerli.json NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/eth-goerli.json
NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Anyblock','baseUrl':'https://explorer.anyblock.tools','paths':{'tx':'/ethereum/poa/core/transaction','address':'/ethereum/poa/core/address'}}] NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Anyblock','baseUrl':'https://explorer.anyblock.tools','paths':{'tx':'/ethereum/poa/core/transaction','address':'/ethereum/poa/core/address','block':'/ethereum/poa/core/block'}}]
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs','coin_price','market_cup'] NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs','coin_price','market_cap']
#NEXT_PUBLIC_HOMEPAGE_PLATE_GRADIENT=linear-gradient(136.9deg, \#235643 1.5%, \#16191E 77.77%) #NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND='no-repeat bottom 20% right 0px/100% url(https://neon-labs.org/images/index/banner.jpg)'
#NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR=\#DCFE76 #NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR=\#DCFE76
NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/network-logos/poa.svg NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/network-logos/poa.svg
NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/network-icons/poa.svg NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/network-icons/poa.svg
......
...@@ -11,10 +11,11 @@ NEXT_PUBLIC_FOOTER_GITHUB_LINK=https://github.com/blockscout/blockscout ...@@ -11,10 +11,11 @@ NEXT_PUBLIC_FOOTER_GITHUB_LINK=https://github.com/blockscout/blockscout
NEXT_PUBLIC_FOOTER_TWITTER_LINK=https://www.twitter.com/blockscoutcom NEXT_PUBLIC_FOOTER_TWITTER_LINK=https://www.twitter.com/blockscoutcom
NEXT_PUBLIC_FOOTER_TELEGRAM_LINK=https://t.me/poa_network NEXT_PUBLIC_FOOTER_TELEGRAM_LINK=https://t.me/poa_network
NEXT_PUBLIC_FOOTER_STAKING_LINK=https://duneanalytics.com/maxaleks/xdai-staking NEXT_PUBLIC_FOOTER_STAKING_LINK=https://duneanalytics.com/maxaleks/xdai-staking
NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Anyblock','baseUrl':'https://explorer.anyblock.tools','paths':{'tx':'/ethereum/poa/core/transaction','address':'/ethereum/poa/core/address'}}] NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Bitquery','baseUrl':'https://explorer.bitquery.io/','paths':{'tx':'/goerli/tx','address':'/goerli/address','token':'/goerli/token','block':'/goerli/block'}},{'title':'Etherscan','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}]
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs','coin_price','market_cup'] NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs','coin_price','market_cap']
NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME=true NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME=true
NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER=true NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER=true
NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND=
NEXT_PUBLIC_FEATURED_NETWORKS= NEXT_PUBLIC_FEATURED_NETWORKS=
NEXT_PUBLIC_NETWORK_LOGO= NEXT_PUBLIC_NETWORK_LOGO=
NEXT_PUBLIC_NETWORK_LOGO_DARK= NEXT_PUBLIC_NETWORK_LOGO_DARK=
...@@ -41,5 +42,7 @@ NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://localhost:3000/marketplace-submit-fo ...@@ -41,5 +42,7 @@ NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://localhost:3000/marketplace-submit-fo
# api config # api config
NEXT_PUBLIC_API_HOST=https://localhost:3003 NEXT_PUBLIC_API_HOST=https://localhost:3003
NEXT_PUBLIC_STATS_API_HOST=https://localhost:3004 NEXT_PUBLIC_STATS_API_HOST=https://localhost:3004
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://localhost:3005
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://localhost:3006
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=xxx NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=xxx
NEXT_PUBLIC_API_BASE_PATH=/ NEXT_PUBLIC_API_BASE_PATH=/
This diff is collapsed.
This diff is collapsed.
...@@ -5,7 +5,7 @@ blockscout: ...@@ -5,7 +5,7 @@ blockscout:
app: blockscout app: blockscout
enabled: true enabled: true
image: image:
_default: &image blockscout/blockscout-optimism-l2-advanced:5.1.2-prerelease-465ba09e _default: &image blockscout/blockscout-optimism-l2-advanced:5.1.4-prerelease-a8c134e4
replicas: replicas:
app: 1 app: 1
# init container # init container
...@@ -385,7 +385,7 @@ frontend: ...@@ -385,7 +385,7 @@ frontend:
_default: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/marketplace/base-goerli.json _default: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/marketplace/base-goerli.json
NEXT_PUBLIC_NETWORK_EXPLORERS: NEXT_PUBLIC_NETWORK_EXPLORERS:
_default: '' _default: ''
NEXT_PUBLIC_HOMEPAGE_PLATE_GRADIENT: NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND:
_default: "linear-gradient(136.9deg,rgb(107 94 236) 1.5%,rgb(0 82 255) 56.84%,rgb(82 62 231) 98.54%)" _default: "linear-gradient(136.9deg,rgb(107 94 236) 1.5%,rgb(0 82 255) 56.84%,rgb(82 62 231) 98.54%)"
NEXT_PUBLIC_NETWORK_TOKEN_ADDRESS: NEXT_PUBLIC_NETWORK_TOKEN_ADDRESS:
_default: '' _default: ''
...@@ -398,9 +398,13 @@ frontend: ...@@ -398,9 +398,13 @@ frontend:
NEXT_PUBLIC_HOMEPAGE_CHARTS: NEXT_PUBLIC_HOMEPAGE_CHARTS:
_default: "['daily_txs']" _default: "['daily_txs']"
NEXT_PUBLIC_IS_TESTNET: NEXT_PUBLIC_IS_TESTNET:
_default: "true" _default: true
NEXT_PUBLIC_VISUALIZE_API_HOST: NEXT_PUBLIC_VISUALIZE_API_HOST:
_default: https://visualizer-optimism-goerli.test.aws-k8s.blockscout.com _default: https://visualizer-optimism-goerli.test.aws-k8s.blockscout.com
NEXT_PUBLIC_CONTRACT_INFO_API_HOST:
_default: https://contracts-info-test.k8s-dev.blockscout.com
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST:
_default: https://admin-rs-test.k8s-dev.blockscout.com
NEXT_PUBLIC_IS_L2_NETWORK: NEXT_PUBLIC_IS_L2_NETWORK:
_default: "true" _default: "true"
NEXT_PUBLIC_L1_BASE_URL: NEXT_PUBLIC_L1_BASE_URL:
......
...@@ -299,12 +299,12 @@ frontend: ...@@ -299,12 +299,12 @@ frontend:
NEXT_PUBLIC_FEATURED_NETWORKS: NEXT_PUBLIC_FEATURED_NETWORKS:
_default: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/eth-goerli.json _default: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/eth-goerli.json
NEXT_PUBLIC_NETWORK_EXPLORERS: NEXT_PUBLIC_NETWORK_EXPLORERS:
_default: "[{'title':'Anyblock','baseUrl':'https://explorer.anyblock.tools','paths':{'tx':'/ethereum/ethereum/goerli/transaction','address':'/ethereum/ethereum/goerli/address'}},{'title':'Etherscan','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address'}}]" _default: "[{'title':'Bitquery','baseUrl':'https://explorer.bitquery.io/','paths':{'tx':'/goerli/tx','address':'/goerli/address','token':'/goerli/token','block':'/goerli/block'}},{'title':'Etherscan','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}]"
# network config # network config
NEXT_PUBLIC_NETWORK_NAME: NEXT_PUBLIC_NETWORK_NAME:
_default: Ethereum _default: Göerli
NEXT_PUBLIC_NETWORK_SHORT_NAME: NEXT_PUBLIC_NETWORK_SHORT_NAME:
_default: Goerli _default: Göerli
NEXT_PUBLIC_NETWORK_ASSETS_PATHNAME: NEXT_PUBLIC_NETWORK_ASSETS_PATHNAME:
_default: ethereum _default: ethereum
NEXT_PUBLIC_NETWORK_LOGO: NEXT_PUBLIC_NETWORK_LOGO:
...@@ -343,9 +343,13 @@ frontend: ...@@ -343,9 +343,13 @@ frontend:
NEXT_PUBLIC_API_HOST: NEXT_PUBLIC_API_HOST:
_default: blockscout.com/eth/goerli _default: blockscout.com/eth/goerli
NEXT_PUBLIC_STATS_API_HOST: NEXT_PUBLIC_STATS_API_HOST:
_default: https://stats-test.aws-k8s.blockscout.com/ _default: https://stats-test.aws-k8s.blockscout.com
NEXT_PUBLIC_VISUALIZE_API_HOST: NEXT_PUBLIC_VISUALIZE_API_HOST:
_default: https://visualizer.aws-k8s.blockscout.com _default: https://visualizer.aws-k8s.blockscout.com
NEXT_PUBLIC_CONTRACT_INFO_API_HOST:
_default: https://contracts-info-test.k8s-dev.blockscout.com
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST:
_default: https://admin-rs-test.k8s-dev.blockscout.com
NEXT_PUBLIC_APP_HOST: NEXT_PUBLIC_APP_HOST:
_default: blockscout.com/eth/goerli _default: blockscout.com/eth/goerli
NEXT_PUBLIC_LOGOUT_URL: NEXT_PUBLIC_LOGOUT_URL:
...@@ -355,7 +359,7 @@ frontend: ...@@ -355,7 +359,7 @@ frontend:
NEXT_PUBLIC_NETWORK_RPC_URL: NEXT_PUBLIC_NETWORK_RPC_URL:
_default: https://rpc.ankr.com/eth_goerli _default: https://rpc.ankr.com/eth_goerli
NEXT_PUBLIC_HOMEPAGE_CHARTS: NEXT_PUBLIC_HOMEPAGE_CHARTS:
_default: "['daily_txs','coin_price','market_cup']" _default: "['daily_txs','coin_price','market_cap']"
NEXT_PUBLIC_API_SPEC_URL: NEXT_PUBLIC_API_SPEC_URL:
_default: https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml _default: https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
NEXT_PUBLIC_MARKETPLACE_CONFIG_URL: NEXT_PUBLIC_MARKETPLACE_CONFIG_URL:
......
...@@ -113,7 +113,7 @@ frontend: ...@@ -113,7 +113,7 @@ frontend:
_default: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/marketplace/base-goerli.json _default: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/marketplace/base-goerli.json
NEXT_PUBLIC_NETWORK_EXPLORERS: NEXT_PUBLIC_NETWORK_EXPLORERS:
_default: '' _default: ''
NEXT_PUBLIC_HOMEPAGE_PLATE_GRADIENT: NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND:
_default: "linear-gradient(136.9deg,rgb(107 94 236) 1.5%,rgb(0 82 255) 56.84%,rgb(82 62 231) 98.54%)" _default: "linear-gradient(136.9deg,rgb(107 94 236) 1.5%,rgb(0 82 255) 56.84%,rgb(82 62 231) 98.54%)"
NEXT_PUBLIC_NETWORK_TOKEN_ADDRESS: NEXT_PUBLIC_NETWORK_TOKEN_ADDRESS:
_default: '' _default: ''
...@@ -126,9 +126,13 @@ frontend: ...@@ -126,9 +126,13 @@ frontend:
NEXT_PUBLIC_HOMEPAGE_CHARTS: NEXT_PUBLIC_HOMEPAGE_CHARTS:
_default: "['daily_txs']" _default: "['daily_txs']"
NEXT_PUBLIC_IS_TESTNET: NEXT_PUBLIC_IS_TESTNET:
_default: "true" _default: true
NEXT_PUBLIC_VISUALIZE_API_HOST: NEXT_PUBLIC_VISUALIZE_API_HOST:
_default: https://visualizer-optimism-goerli.test.aws-k8s.blockscout.com _default: https://visualizer-optimism-goerli.test.aws-k8s.blockscout.com
NEXT_PUBLIC_CONTRACT_INFO_API_HOST:
_default: https://contracts-info-test.k8s-dev.blockscout.com
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST:
_default: https://admin-rs-test.k8s-dev.blockscout.com
NEXT_PUBLIC_IS_L2_NETWORK: NEXT_PUBLIC_IS_L2_NETWORK:
_default: "true" _default: "true"
NEXT_PUBLIC_L1_BASE_URL: NEXT_PUBLIC_L1_BASE_URL:
......
...@@ -39,6 +39,7 @@ frontend: ...@@ -39,6 +39,7 @@ frontend:
- "/csv-export" - "/csv-export"
- "/verified-contracts" - "/verified-contracts"
- "/graphiql" - "/graphiql"
- "/login"
resources: resources:
limits: limits:
...@@ -67,9 +68,9 @@ frontend: ...@@ -67,9 +68,9 @@ frontend:
NEXT_PUBLIC_FOOTER_STAKING_LINK: NEXT_PUBLIC_FOOTER_STAKING_LINK:
_default: https://duneanalytics.com/maxaleks/xdai-staking _default: https://duneanalytics.com/maxaleks/xdai-staking
NEXT_PUBLIC_NETWORK_NAME: NEXT_PUBLIC_NETWORK_NAME:
_default: Ethereum _default: Göerli
NEXT_PUBLIC_NETWORK_SHORT_NAME: NEXT_PUBLIC_NETWORK_SHORT_NAME:
_default: Goerli _default: Göerli
NEXT_PUBLIC_NETWORK_ASSETS_PATHNAME: NEXT_PUBLIC_NETWORK_ASSETS_PATHNAME:
_default: ethereum _default: ethereum
NEXT_PUBLIC_NETWORK_LOGO: NEXT_PUBLIC_NETWORK_LOGO:
...@@ -97,6 +98,10 @@ frontend: ...@@ -97,6 +98,10 @@ frontend:
_default: https://stats-test.aws-k8s.blockscout.com/ _default: https://stats-test.aws-k8s.blockscout.com/
NEXT_PUBLIC_VISUALIZE_API_HOST: NEXT_PUBLIC_VISUALIZE_API_HOST:
_default: https://visualizer.aws-k8s.blockscout.com _default: https://visualizer.aws-k8s.blockscout.com
NEXT_PUBLIC_CONTRACT_INFO_API_HOST:
_default: https://contracts-info-test.k8s-dev.blockscout.com
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST:
_default: https://admin-rs-test.k8s-dev.blockscout.com
NEXT_PUBLIC_AUTH_URL: NEXT_PUBLIC_AUTH_URL:
_default: https://blockscout-main.test.aws-k8s.blockscout.com _default: https://blockscout-main.test.aws-k8s.blockscout.com
NEXT_PUBLIC_API_BASE_PATH: NEXT_PUBLIC_API_BASE_PATH:
...@@ -109,13 +114,13 @@ frontend: ...@@ -109,13 +114,13 @@ frontend:
_default: https://blockscout.com/auth/logout _default: https://blockscout.com/auth/logout
review: blockscout-main.test.aws-k8s.blockscout.com/auth/logout review: blockscout-main.test.aws-k8s.blockscout.com/auth/logout
NEXT_PUBLIC_HOMEPAGE_CHARTS: NEXT_PUBLIC_HOMEPAGE_CHARTS:
_default: "['daily_txs','coin_price','market_cup']" _default: "['daily_txs','coin_price','market_cap']"
NEXT_PUBLIC_APP_HOST: NEXT_PUBLIC_APP_HOST:
_default: blockscout.com _default: blockscout.com
NEXT_PUBLIC_NETWORK_RPC_URL: NEXT_PUBLIC_NETWORK_RPC_URL:
_default: https://rpc.ankr.com/eth_goerli _default: https://rpc.ankr.com/eth_goerli
NEXT_PUBLIC_NETWORK_EXPLORERS: NEXT_PUBLIC_NETWORK_EXPLORERS:
_default: "[{'title':'Anyblock','baseUrl':'https://explorer.anyblock.tools','paths':{'tx':'/ethereum/ethereum/goerli/transaction','address':'/ethereum/ethereum/goerli/address'}},{'title':'Etherscan','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address'}}]" _default: "[{'title':'Bitquery','baseUrl':'https://explorer.bitquery.io/','paths':{'tx':'/goerli/tx','address':'/goerli/address','token':'/goerli/token','block':'/goerli/block'}},{'title':'Etherscan','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}]"
NEXT_PUBLIC_API_SPEC_URL: NEXT_PUBLIC_API_SPEC_URL:
_default: https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml _default: https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
NEXT_PUBLIC_MARKETPLACE_CONFIG_URL: NEXT_PUBLIC_MARKETPLACE_CONFIG_URL:
......
...@@ -29,6 +29,7 @@ The app instance could be customized by passing following variables to NodeJS en ...@@ -29,6 +29,7 @@ The app instance could be customized by passing following variables to NodeJS en
| Variable | Type| Description | Is required | Default value | Example value | | Variable | Type| Description | Is required | Default value | Example value |
| --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- | --- |
| NEXT_PUBLIC_FEATURED_NETWORKS | `string` | URL of configuration file (`.json` format only) which contains list of featured networks that will be shown in the network menu. See [below](#featured-network-configuration-properties) list of available properties for particular network | - | - | `https://example.com/featured_networks_config.json` | | NEXT_PUBLIC_FEATURED_NETWORKS | `string` | URL of configuration file (`.json` format only) which contains list of featured networks that will be shown in the network menu. See [below](#featured-network-configuration-properties) list of available properties for particular network | - | - | `https://example.com/featured_networks_config.json` |
| NEXT_PUBLIC_OTHER_LINKS | `Array<{url: string; text: string}>` | List of links for the "Other" navigation menu | - | - | `[{'url':'https://blockscout.com','text':'Blockscout'}]` |
| NEXT_PUBLIC_BLOCKSCOUT_VERSION | `string` | Current running version of Blockscout (used to display link to release in the footer) | - | - | `v.5.1.0-beta` | NEXT_PUBLIC_BLOCKSCOUT_VERSION | `string` | Current running version of Blockscout (used to display link to release in the footer) | - | - | `v.5.1.0-beta`
| NEXT_PUBLIC_FOOTER_GITHUB_LINK | `string` | Link to Github in the footer | - | - | `https://github.com/blockscout/blockscout` | | NEXT_PUBLIC_FOOTER_GITHUB_LINK | `string` | Link to Github in the footer | - | - | `https://github.com/blockscout/blockscout` |
| NEXT_PUBLIC_FOOTER_TWITTER_LINK | `string` | Link to Twitter in the footer | - | - | `https://www.twitter.com/blockscoutcom` | | NEXT_PUBLIC_FOOTER_TWITTER_LINK | `string` | Link to Twitter in the footer | - | - | `https://www.twitter.com/blockscoutcom` |
...@@ -41,9 +42,9 @@ The app instance could be customized by passing following variables to NodeJS en ...@@ -41,9 +42,9 @@ The app instance could be customized by passing following variables to NodeJS en
| NEXT_PUBLIC_AUTH_URL | `string` | Account auth base url; the login path (`/auth/auth0`) will be added to it at execution time. Required if account is supported for the app instance. | - | - | `https://blockscout.com` | | NEXT_PUBLIC_AUTH_URL | `string` | Account auth base url; the login path (`/auth/auth0`) will be added to it at execution time. Required if account is supported for the app instance. | - | - | `https://blockscout.com` |
| NEXT_PUBLIC_LOGOUT_URL | `string` | Account logout url. Required if account is supported for the app instance. | - | - | `https://blockscoutcom.us.auth0.com/v2/logout` | | NEXT_PUBLIC_LOGOUT_URL | `string` | Account logout url. Required if account is supported for the app instance. | - | - | `https://blockscoutcom.us.auth0.com/v2/logout` |
| NEXT_PUBLIC_LOGOUT_RETURN_URL | `string` | Account logout return url. Required if account is supported for the app instance. | - | - | `https://blockscout.com/poa/core/auth/logout` | | NEXT_PUBLIC_LOGOUT_RETURN_URL | `string` | Account logout return url. Required if account is supported for the app instance. | - | - | `https://blockscout.com/poa/core/auth/logout` |
| NEXT_PUBLIC_HOMEPAGE_CHARTS | `Array<'daily_txs' \| 'coin_price' \| 'market_cup'>` | List of charts displayed on the home page | - | - | `['daily_txs','coin_price','market_cup']` | | NEXT_PUBLIC_HOMEPAGE_CHARTS | `Array<'daily_txs' \| 'coin_price' \| 'market_cap'>` | List of charts displayed on the home page | - | - | `['daily_txs','coin_price','market_cap']` |
| NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR | `string` | Text color of the hero plate on the homepage (escape "#" symbol if you use HEX color codes) | `\#FFFFFF \| rgb(220, 254, 118)` | `\#DCFE76` | | NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR | `string` | Text color of the hero plate on the homepage (escape "#" symbol if you use HEX color codes) | `\#FFFFFF \| rgb(220, 254, 118)` | `\#DCFE76` |
| NEXT_PUBLIC_HOMEPAGE_PLATE_GRADIENT | `string` | Gradient value for hero plate on the homepage (escape "#" symbol if you use HEX color codes) | - | `radial-gradient(103.03% 103.03% at 0% 0%, rgba(183, 148, 244, 0.8) 0%, rgba(0, 163, 196, 0.8) 100%)` | `radial-gradient(at 15% 86%, hsla(350,65%,70%,1) 0px, transparent 50%), radial-gradient(at 72% 57%, hsla(14,95%,76%,1) 0px, transparent 50%)` | | NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND | `string` | Background css value for hero plate on the homepage (escape "#" symbol if you use HEX color codes) | - | `radial-gradient(103.03% 103.03% at 0% 0%, rgba(183, 148, 244, 0.8) 0%, rgba(0, 163, 196, 0.8) 100%), var(--chakra-colors-blue-400)` | `radial-gradient(at 15% 86%, hsla(350,65%,70%,1) 0px, transparent 50%)` \| `no-repeat bottom 20% right 0px/100% url(https://placekitten/1400/200)` |
| NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER | `boolean` | Set to false if network doesn't have gas tracker | - | `true` | `false` | | NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER | `boolean` | Set to false if network doesn't have gas tracker | - | `true` | `false` |
| NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME | `boolean` | Set to false if average block time is useless for the network | - | `true` | `false` | | NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME | `boolean` | Set to false if average block time is useless for the network | - | `true` | `false` |
| NEXT_PUBLIC_AD_DOMAIN_WITH_AD | `string` | The domain on which we display ads | - | - | `blockscout.com` | | NEXT_PUBLIC_AD_DOMAIN_WITH_AD | `string` | The domain on which we display ads | - | - | `blockscout.com` |
...@@ -103,7 +104,7 @@ For each application, you need to specify the `MarketplaceCategoryId` to which i ...@@ -103,7 +104,7 @@ For each application, you need to specify the `MarketplaceCategoryId` to which i
| --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- | --- |
| title | `string` | Displayed name of the explorer | yes | - | `Anyblock` | | title | `string` | Displayed name of the explorer | yes | - | `Anyblock` |
| baseUrl | `string` | Base url of the explorer | yes | - | `https://explorer.anyblock.tools` | | baseUrl | `string` | Base url of the explorer | yes | - | `https://explorer.anyblock.tools` |
| paths | `Record<'tx' \| 'block' \| 'address', string>` | Map of explorer entities and their paths | yes | - | `{'tx':'/ethereum/poa/core/tx'}` | | paths | `Record<'tx' \| 'block' \| 'address' \| 'token', string>` | Map of explorer entities and their paths | yes | - | `{'tx':'/ethereum/poa/core/tx'}` |
*Note* The url of an entity will be constructed as `<baseUrl><paths[<entity-type>]><entity-id>`, e.g `https://explorer.anyblock.tools/ethereum/poa/core/tx/<tx-id>` *Note* The url of an entity will be constructed as `<baseUrl><paths[<entity-type>]><entity-id>`, e.g `https://explorer.anyblock.tools/ethereum/poa/core/tx/<tx-id>`
...@@ -128,6 +129,8 @@ For each application, you need to specify the `MarketplaceCategoryId` to which i ...@@ -128,6 +129,8 @@ For each application, you need to specify the `MarketplaceCategoryId` to which i
| NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL | `ws \| wss` | Main API websocket protocol | - | `wss` | `ws` | | NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL | `ws \| wss` | Main API websocket protocol | - | `wss` | `ws` |
| NEXT_PUBLIC_STATS_API_HOST | `string` | Stats API endpoint url | - | - | `https://my-host.com` | | NEXT_PUBLIC_STATS_API_HOST | `string` | Stats API endpoint url | - | - | `https://my-host.com` |
| NEXT_PUBLIC_VISUALIZE_API_HOST | `string` | Visualize API endpoint url | - | - | `https://my-host.com` | | NEXT_PUBLIC_VISUALIZE_API_HOST | `string` | Visualize API endpoint url | - | - | `https://my-host.com` |
| NEXT_PUBLIC_CONTRACT_INFO_API_HOST | `string` | Contract Info API endpoint url | - | - | `https://my-host.com` |
| NEXT_PUBLIC_ADMIN_SERVICE_API_HOST | `string` | Admin Service API endpoint url | - | - | `https://my-host.com` |
## External services configuration ## External services configuration
......
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.26 17.5H4.027a.47.47 0 0 1-.47-.469V5.312c0-.26.21-.469.47-.469h2.137V2.969c0-.259.21-.469.468-.469h5.89l.015.003.014.003a.449.449 0 0 1 .14.03.463.463 0 0 1 .156.095l3.452 3.31-.002.002a.466.466 0 0 1 .146.337v7.3c0 .87-.708 1.577-1.577 1.577h-1.029v.766c0 .87-.707 1.577-1.577 1.577Zm2.823-11.69L12.99 3.794v1.379a.64.64 0 0 0 .638.639h1.454Zm-2.755-2.648H6.826v11.333h8.316a.64.64 0 0 0 .639-.64V6.474H13.63c-.87 0-1.302-.432-1.302-1.301v-2.01ZM6.164 5.505H4.22v11.333h8.316c.352 0 .639-.563.639-.915v-.766H6.632a.469.469 0 0 1-.468-.469V5.505ZM8.85 8.5a.25.25 0 1 0 0 .5h4.7a.25.25 0 1 0 0-.5h-4.7Zm-.25 1.95a.25.25 0 0 1 .25-.25h4.7a.25.25 0 1 1 0 .5h-4.7a.25.25 0 0 1-.25-.25ZM8.85 12a.25.25 0 1 0 0 .5h4.7a.25.25 0 1 0 0-.5h-4.7Z" fill="currentColor"/>
<path d="M6.164 4.843v.35h.35v-.35h-.35Zm6.373-2.34-.098.336h.003l.095-.336Zm0 0 .099-.336h-.003l-.095.336Zm.014.003.02-.35-.02.35Zm.123.025.12-.33h-.004l-.115.33Zm.017.005.101-.335-.101.335Zm.025.009.145-.319h-.002l-.143.319Zm.13.086.243-.253-.243.252ZM16.3 5.94l.247.248.253-.253-.258-.247-.242.252Zm-.002.002-.247-.248-.252.252.257.248.242-.252Zm-2.46 9.214v-.35h-.35v.35h.35Zm-.846-11.364.242-.252-.593-.572v.824h.35Zm2.092 2.018v.35h.867l-.624-.602-.243.252ZM6.826 3.162v-.35h-.35v.35h.35Zm5.502 0h.35v-.35h-.35v.35ZM6.826 14.495h-.35v.35h.35v-.35Zm8.955-8.022h.35v-.35h-.35v.35ZM4.22 5.505v-.35h-.35v.35h.35Zm1.944 0h.35v-.35h-.35v.35ZM4.22 16.838h-.35v.35h.35v-.35Zm8.955-1.68h.35v-.35h-.35v.35ZM4.027 17.85h8.233v-.7H4.027v.7Zm-.82-.819a.82.82 0 0 0 .82.819v-.7a.12.12 0 0 1-.12-.119h-.7Zm0-11.719v11.719h.7V5.312h-.7Zm.82-.819a.82.82 0 0 0-.82.819h.7a.12.12 0 0 1 .12-.119v-.7Zm2.137 0H4.027v.7h2.137v-.7Zm-.35-1.524v1.874h.7V2.969h-.7Zm.818-.819a.819.819 0 0 0-.818.819h.7c0-.066.053-.119.118-.119v-.7Zm5.89 0h-5.89v.7h5.89v-.7Zm.114.017s-.015-.005-.033-.008a.389.389 0 0 0-.081-.009v.7a.313.313 0 0 1-.065-.007c-.013-.002-.022-.006-.018-.004l.197-.672Zm-.003 0-.191.673.191-.674Zm-.063-.01a.308.308 0 0 1 .053.007l.013.003-.197.672.027.007a.39.39 0 0 0 .066.01l.038-.7Zm.22.043a.8.8 0 0 0-.218-.044l-.041.7a.1.1 0 0 1 .028.005l.231-.66Zm.002 0 .001.001-.237.659c.015.005.029.01.033.01l.203-.67Zm.067.025c-.032-.014-.061-.022-.067-.024l-.203.67h.004-.002a.208.208 0 0 1-.018-.007l.286-.639Zm.23.153a.812.812 0 0 0-.228-.152l-.29.637a.11.11 0 0 1 .033.02l.485-.505Zm3.452 3.31-3.452-3.31-.485.505 3.453 3.311.484-.505Zm.004.502.001-.001-.495-.495-.001.001.495.495Zm.248.09a.818.818 0 0 0-.253-.59l-.485.505a.117.117 0 0 1 .038.085h.7Zm0 7.3v-7.3h-.7v7.3h.7Zm-1.927 1.927a1.929 1.929 0 0 0 1.927-1.927h-.7c0 .677-.551 1.227-1.227 1.227v.7Zm-1.029 0h1.029v-.7h-1.029v.7Zm.35.416v-.766h-.7v.766h.7ZM12.26 17.85a1.929 1.929 0 0 0 1.927-1.927h-.7c0 .676-.55 1.227-1.227 1.227v.7Zm.488-13.805 2.092 2.018.486-.504-2.093-2.018-.486.504Zm.593 1.127v-1.38h-.7v1.38h.7Zm.288.289a.29.29 0 0 1-.288-.29h-.7a.99.99 0 0 0 .988.99v-.7Zm1.454 0h-1.454v.7h1.454v-.7ZM6.826 3.512h5.502v-.7H6.826v.7Zm.35 10.983V3.162h-.7v11.333h.7Zm7.966-.35H6.826v.7h8.316v-.7Zm.289-.29a.29.29 0 0 1-.29.29v.7a.99.99 0 0 0 .99-.99h-.7Zm0-7.382v7.383h.7V6.473h-.7Zm-1.801.35h2.15v-.7h-2.15v.7Zm-1.652-1.651c0 .488.122.918.427 1.224.306.306.737.427 1.225.427v-.7c-.382 0-.602-.095-.73-.222-.127-.127-.222-.348-.222-.73h-.7Zm0-2.01v2.01h.7v-2.01h-.7ZM4.22 5.855h1.944v-.7H4.22v.7Zm.35 10.983V5.505h-.7v11.333h.7Zm7.966-.35H4.22v.7h8.316v-.7Zm.289-.565a.862.862 0 0 1-.134.404c-.099.156-.167.16-.155.16v.7c.364 0 .615-.276.748-.489.143-.229.24-.52.24-.775h-.7Zm0-.766v.766h.7v-.766h-.7Zm-6.193.35h6.543v-.7H6.632v.7Zm-.818-.819c0 .452.365.82.818.82v-.7a.119.119 0 0 1-.118-.12h-.7Zm0-9.183v9.183h.7V5.505h-.7ZM8.95 8.75a.1.1 0 0 1-.1.1v-.7a.6.6 0 0 0-.6.6h.7Zm-.1-.1a.1.1 0 0 1 .1.1h-.7a.6.6 0 0 0 .6.6v-.7Zm4.7 0h-4.7v.7h4.7v-.7Zm-.1.1a.1.1 0 0 1 .1-.1v.7a.6.6 0 0 0 .6-.6h-.7Zm.1.1a.1.1 0 0 1-.1-.1h.7a.6.6 0 0 0-.6-.6v.7Zm-4.7 0h4.7v-.7h-4.7v.7Zm0 1a.6.6 0 0 0-.6.6h.7a.1.1 0 0 1-.1.1v-.7Zm4.7 0h-4.7v.7h4.7v-.7Zm.6.6a.6.6 0 0 0-.6-.6v.7a.1.1 0 0 1-.1-.1h.7Zm-.6.6a.6.6 0 0 0 .6-.6h-.7a.1.1 0 0 1 .1-.1v.7Zm-4.7 0h4.7v-.7h-4.7v.7Zm-.6-.6a.6.6 0 0 0 .6.6v-.7a.1.1 0 0 1 .1.1h-.7Zm.7 1.8a.1.1 0 0 1-.1.1v-.7a.6.6 0 0 0-.6.6h.7Zm-.1-.1a.1.1 0 0 1 .1.1h-.7a.6.6 0 0 0 .6.6v-.7Zm4.7 0h-4.7v.7h4.7v-.7Zm-.1.1a.1.1 0 0 1 .1-.1v.7a.6.6 0 0 0 .6-.6h-.7Zm.1.1a.1.1 0 0 1-.1-.1h.7a.6.6 0 0 0-.6-.6v.7Zm-4.7 0h4.7v-.7h-4.7v.7Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M21 5H3v13.58h18V5ZM4.256 7.163v9.25L8.8 11.766 4.256 7.163Zm14.622 10.16H5.12l4.56-4.662.879.89c.782.788 2.156.78 2.925.006l.865-.87 4.528 4.637Zm.866-.91V7.257l-4.51 4.539 4.51 4.617ZM18.97 6.256H5.125l6.327 6.411c.29.292.864.286 1.142.005l6.375-6.416Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 201 101" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M127.992 76.305c0 3.301-.633 6.4-1.9 9.294-1.221 2.895-2.917 5.428-5.088 7.599-2.171 2.17-4.704 3.89-7.598 5.156-2.895 1.22-5.993 1.831-9.295 1.831h-4.138c-3.302 0-6.423-.61-9.362-1.831-2.895-1.267-5.428-2.986-7.599-5.156-2.17-2.171-3.89-4.704-5.156-7.599-1.221-2.895-1.832-5.993-1.832-9.294v-52.24c0-3.3.611-6.399 1.832-9.294 1.267-2.894 2.985-5.427 5.156-7.598 2.171-2.17 4.704-3.867 7.599-5.088 2.94-1.266 6.06-1.9 9.362-1.9h4.138c3.302 0 6.4.633 9.295 1.9 2.894 1.221 5.427 2.917 7.598 5.088 2.171 2.171 3.867 4.704 5.088 7.598 1.267 2.895 1.9 5.993 1.9 9.295v52.239Zm-8.752-52.24c0-2.17-.407-4.183-1.221-6.037-.814-1.9-1.922-3.55-3.324-4.953-1.402-1.402-3.053-2.51-4.953-3.324-1.854-.814-3.867-1.221-6.038-1.221h-3.324c-2.171 0-4.206.407-6.106 1.221a16.718 16.718 0 0 0-4.952 3.324c-1.403 1.402-2.51 3.053-3.325 4.953-.814 1.854-1.22 3.867-1.22 6.038v52.239c0 2.17.406 4.206 1.22 6.105a16.72 16.72 0 0 0 3.325 4.953 16.72 16.72 0 0 0 4.952 3.324c1.9.814 3.935 1.222 6.106 1.222h3.324c2.171 0 4.184-.408 6.038-1.222 1.9-.814 3.551-1.922 4.953-3.324a16.72 16.72 0 0 0 3.324-4.953c.814-1.9 1.221-3.934 1.221-6.105v-52.24Zm-71.411 57.94v16.824a8.752 8.752 0 0 1-8.752-8.751v-8.073H3.275a3.275 3.275 0 0 1-2.85-4.89L42.38 3.021a2.914 2.914 0 0 1 5.45 1.436v69.202h8.345a8.345 8.345 0 0 1-8.345 8.344ZM39.077 25.49 12.28 73.659h26.797V25.49ZM198.22 86.25c1.276-2.917 1.914-6.039 1.914-9.365v-6.7c0-2.324-.319-4.534-.957-6.63a22.47 22.47 0 0 0-2.598-5.948 22.916 22.916 0 0 0-3.965-4.922 22.222 22.222 0 0 0-5.195-3.76 25.193 25.193 0 0 0 5.195-3.76 24.48 24.48 0 0 0 3.965-4.99 22.69 22.69 0 0 0 2.598-5.878c.638-2.142.957-4.375.957-6.7v-3.35c0-3.326-.638-6.448-1.914-9.364-1.231-2.917-2.94-5.47-5.127-7.657-2.188-2.187-4.74-3.896-7.657-5.127C182.519.823 179.397.185 176.07.185h-4.17c-3.327 0-6.471.638-9.433 1.914-2.917 1.23-5.469 2.94-7.657 5.127-2.187 2.188-3.919 4.74-5.195 7.657-1.23 2.916-1.846 6.038-1.846 9.365a2.974 2.974 0 0 0 2.497 2.935l2.408.393a3.372 3.372 0 0 0 3.914-3.328c0-2.188.41-4.216 1.23-6.084.82-1.914 1.937-3.578 3.35-4.99a16.835 16.835 0 0 1 4.99-3.35c1.914-.82 3.965-1.23 6.152-1.23h3.35c2.187 0 4.215.41 6.084 1.23 1.914.82 3.577 1.937 4.99 3.35 1.413 1.412 2.529 3.076 3.35 4.99.82 1.868 1.23 3.896 1.23 6.084v4.785c0 2.188-.41 4.238-1.23 6.152a15.982 15.982 0 0 1-3.35 4.922c-1.413 1.413-3.076 2.53-4.99 3.35-1.869.82-3.897 1.23-6.084 1.23h-2.358a4.205 4.205 0 1 0 0 8.409h2.358c2.187 0 4.215.41 6.084 1.23 1.914.82 3.577 1.937 4.99 3.35 1.413 1.412 2.529 3.076 3.35 4.99.82 1.868 1.23 3.896 1.23 6.084v8.135c0 2.187-.41 4.238-1.23 6.152a16.856 16.856 0 0 1-3.35 4.99c-1.413 1.413-3.076 2.53-4.99 3.35-1.869.82-3.897 1.23-6.084 1.23h-3.35c-2.187 0-4.238-.41-6.152-1.23a16.834 16.834 0 0 1-4.99-3.35 16.837 16.837 0 0 1-3.35-4.99c-.82-1.914-1.23-3.965-1.23-6.153a3.34 3.34 0 0 0-3.851-3.299l-2.468.383a2.952 2.952 0 0 0-2.5 2.916c0 3.327.616 6.45 1.846 9.366 1.276 2.916 3.008 5.469 5.195 7.656 2.188 2.188 4.74 3.92 7.657 5.195 2.962 1.231 6.106 1.846 9.433 1.846h4.17c3.327 0 6.449-.615 9.365-1.846 2.917-1.276 5.469-3.007 7.657-5.195 2.187-2.188 3.896-4.74 5.127-7.656Z" fill="currentColor"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
<g fill="currentColor" clip-path="url(#explorer_svg__a)">
<path d="M14.192 5.808a.624.624 0 0 0-.64-.15L7.927 7.531a.625.625 0 0 0-.395.395l-1.875 5.625a.625.625 0 0 0 .79.791l5.626-1.875a.626.626 0 0 0 .395-.395l1.875-5.625a.625.625 0 0 0-.151-.64Zm-6.954 6.954L8.62 8.619l2.762 2.762-4.143 1.38Z"/>
<path d="M10 18.75A8.75 8.75 0 1 1 18.75 10 8.76 8.76 0 0 1 10 18.75ZM10 2.5a7.5 7.5 0 1 0 7.5 7.5A7.509 7.509 0 0 0 10 2.5Z"/>
</g>
<defs>
<clipPath id="explorer_svg__a">
<path fill="currentColor" d="M0 0h20v20H0z"/>
</clipPath>
</defs>
</svg>
<svg viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#link_svg__a)"> <path fill-rule="evenodd" clip-rule="evenodd" d="M16.17 3a5.073 5.073 0 0 0-3.568 1.424l-.01.01-1.401 1.393a1 1 0 0 0 1.41 1.419l1.396-1.388a3.073 3.073 0 0 1 4.346 4.344l-2.437 2.438a3.072 3.072 0 0 1-4.635-.332 1 1 0 1 0-1.601 1.198 5.074 5.074 0 0 0 7.65.548l2.444-2.444.012-.012A5.073 5.073 0 0 0 16.17 3Zm-5.34 5.657a5.073 5.073 0 0 0-3.95 1.474l-2.444 2.444-.012.012a5.073 5.073 0 0 0 7.174 7.174l.012-.013 1.393-1.393a1 1 0 1 0-1.414-1.414l-1.387 1.387a3.073 3.073 0 0 1-4.345-4.346l2.437-2.437a3.072 3.072 0 0 1 4.635.332 1 1 0 0 0 1.601-1.198 5.074 5.074 0 0 0-3.7-2.022Z" fill="currentColor"/>
<path d="M5.547 6.073c1.303-1.303 3.469-1.303 4.772 0 1.171 1.172 1.345 3.04.382 4.387l-.026.038a.75.75 0 0 1-1.221-.872l.026-.038a1.89 1.89 0 0 0-2.874-2.435l-2.63 2.632c-.738.717-.738 1.934 0 2.672a1.887 1.887 0 0 0 2.433.202l.038-.047a.772.772 0 0 1 1.045.194.75.75 0 0 1-.173 1.048l-.038.026a3.389 3.389 0 0 1-4.366-5.154l2.632-2.653Zm6.914 5.833A3.388 3.388 0 0 1 7.307 7.54l.026-.038c.22-.335.689-.415 1.045-.173.338.22.417.689.176 1.045l-.026.038c-.537.731-.452 1.781.202 2.435a1.893 1.893 0 0 0 2.671 0l2.63-2.632c.738-.738.738-1.955 0-2.672a1.887 1.887 0 0 0-2.433-.202l-.037.026c-.338.242-.806.143-1.046-.174a.749.749 0 0 1 .174-1.046l.037-.026a3.389 3.389 0 0 1 4.367 5.153l-2.632 2.632Z" fill="currentColor"/>
</g>
<defs>
<clipPath id="link_svg__a">
<path fill="#fff" transform="translate(1.504 3)" d="M0 0h15v12H0z"/>
</clipPath>
</defs>
</svg> </svg>
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 9.375a1.25 1.25 0 1 0 0-2.5 1.25 1.25 0 0 0 0 2.5Z" stroke="currentColor" stroke-width="1.4" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.25 9.938c-1.188.937-2.125 2.25-2.5 3.812h1.438c.937 0 1.625-.875 1.375-1.75a9.626 9.626 0 0 1-.375-2.688C6.25 5.876 7.813 2.939 10 1.875c2.188 1.063 3.75 4 3.75 7.375 0 .938-.125 1.875-.375 2.688-.25.874.438 1.75 1.375 1.75h1.5c-.375-1.563-1.313-2.938-2.5-3.813M10 13.75v5M8.125 15v2.5m3.75-2.5v2.5" stroke="currentColor" stroke-width="1.4" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.2 2a9.996 9.996 0 0 1 10.014 10.026c0 5.483-4.523 10-10.092 9.974-5.385-.052-9.908-4.49-9.908-10 0-5.535 4.444-10.026 9.987-10ZM4.594 17.222c0 .104.052.156.105.235.392.548.836 1.07 1.359 1.514.235.21.47.418.732.6.732.47 1.49.914 2.327 1.202.68.235 1.385.418 2.091.496.55.052 1.124.078 1.673 0 .314-.052.654-.052.968-.183.052.026-.026-.958 0-.958.653-.105.392-.896 1.02-1.157 2.039-.887 2.797-1.828 3.79-3.812.89-1.75 1.726-2.767 1.438-4.7-.261-1.853-1.882-2.428-3.137-3.785-1.673-1.906-1.908-2.455-4.444-2.611-1.125-.079-1.15.81-2.223 1.175-1.751.574-3.059.391-4.235 1.827C4.724 8.71 4.776 9.911 4.697 12c-.026.522-.182 1.332-.104 1.854.157 1.175-1.02 1.801-.418 2.82.157.156.261.365.418.548Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.253 7.04c-.575-.105-1.15-.21-1.752-.183-.653.026-1.228.235-1.83.47-.705.26-1.359.626-1.882 1.174-.575.601-.889 1.332-1.02 2.168-.104.704-.13 1.41-.209 2.114-.13 1.515-.366 3.03-.993 4.413-.183-.157-.288-.392-.392-.575a8.801 8.801 0 0 1-1.15-3.315c-.079-.523-.131-1.019-.105-1.54.078-2.09.732-3.97 2.065-5.614C6.135 4.716 7.6 3.723 9.351 3.149a9.54 9.54 0 0 1 3.32-.444c2.51.157 4.654 1.175 6.353 3.029a9.16 9.16 0 0 1 2.301 4.83c.288 1.932 0 3.786-.889 5.535-.993 1.985-2.536 3.42-4.575 4.308a7.7 7.7 0 0 1-1.909.575c-.052 0-.078.078-.104.026-.157-.992.078-1.932.47-2.846.497-1.097 1.203-2.037 1.987-2.95.654-.758 1.412-1.463 2.144-2.168.418-.417.785-.835.994-1.383.366-.888.157-1.62-.628-2.194-.601-.443-1.307-.678-2.013-.887a26.36 26.36 0 0 1-2.013-.731c-.13-.444-.444-.731-.863-.888-.549-.13-1.098-.078-1.673.078Zm8.55 5.56h.052c.104-.365.104-.757.104-1.148 0-.444-.052-.888-.13-1.332a7.48 7.48 0 0 0-1.962-3.76c-.627-.652-1.333-1.2-2.039-1.775-.627-.522-1.307-.914-2.091-1.123-.758-.182-1.49-.287-2.275-.156-.052 0-.104 0-.104.052s.052.052.104.052c1.15.209 2.249.575 3.32.992 1.046.418 1.935 1.019 2.589 1.958.444.653.863 1.332 1.202 2.063.445.992.785 2.01.994 3.055.105.418.183.757.235 1.123Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.894 7.927c.993 0 1.778.81 1.778 1.775 0 .992-.81 1.776-1.804 1.802-.994 0-1.778-.81-1.778-1.802s.81-1.775 1.804-1.775Zm1.255 1.801c0-.705-.55-1.253-1.255-1.253-.706 0-1.255.548-1.255 1.253 0 .68.55 1.254 1.229 1.254h.026c.68 0 1.229-.549 1.255-1.254Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.358 13.41c.68.418 1.438.47 2.196.444a8.302 8.302 0 0 0 2.98-.705c.367-.157.733-.314 1.072-.522.027-.027.053-.053.105-.027-.026.079-.105.105-.183.157-1.02.679-2.144 1.097-3.346 1.332-.68.13-1.386.13-2.04-.105-.34-.13-.653-.34-.784-.574Zm-.104-6.37c.549-.158 1.124-.21 1.673 0 .418.156.732.443.862.887-.784-.418-1.647-.679-2.535-.888Z" fill="transparent"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.358 13.41c.68.417 1.438.469 2.196.443a8.304 8.304 0 0 0 2.98-.705c.367-.157.733-.313 1.073-.522.026-.026.052-.052.104-.026-.026.078-.104.104-.183.156-1.02.68-2.144 1.097-3.346 1.332-.68.13-1.386.13-2.04-.104-.34-.131-.653-.34-.784-.575Zm4.942-1.54a.402.402 0 0 1-.393-.392c0-.21.157-.392.366-.392.21 0 .392.157.418.365-.026.236-.183.418-.392.418Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.815 12.523a.056.056 0 0 1-.052.052c0-.052.026-.078.052-.052Zm.078-.052-.078.052-.026-.026c.052-.026.078-.026.104-.026Z" fill="transparent"/>
</svg>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.59 14.774c.245-.016.482-.099.684-.238h.004c.197-.125.369-.288.511-.484.138-.662.211-1.349.211-2.052 0-5.523-4.477-10-10-10S2 6.477 2 12c0 1.55.352 3.017.981 4.326l5.643-9.058c.733-1.118 1.486-1.178 1.989-1.03.76.22 1.161.96 1.191 2.195v5.356l2.712-4.388.02-.034c.457-.73 1.59-2.544 3.1-2.102.907.264 1.449 1.239 1.449 2.608v2.852c0 .93.278 1.613.793 1.905.22.11.465.16.711.144Zm-.018 2.38a3.683 3.683 0 0 1-1.808-.442c-1.28-.717-2.009-2.17-2.009-3.987v-2.48c-.08.116-.17.25-.264.408l-3.013 4.877c-1.014 1.647-1.982 1.774-2.614 1.59-.633-.184-1.386-.813-1.386-2.758v-4.047L4.392 18.49A9.978 9.978 0 0 0 12 22a9.995 9.995 0 0 0 8.572-4.847Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="m8.074 22 .128-3.79a13.266 13.266 0 0 1-5.491 1.181v.805a1.803 1.803 0 0 0 1.803 1.805h3.56Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.631 2h2.797a9.95 9.95 0 0 1 4.552 1.094 13.202 13.202 0 0 0-1.871 2.688.873.873 0 0 0-.633.03.942.942 0 0 0-1.806 0 .922.922 0 0 0-1.09.287.913.913 0 0 0-.126.207c-.24-.328-.586-.533-.96-.754-.309-.183-.637-.377-.937-.661a.266.266 0 0 0-.406.02.534.534 0 0 0-.058.54c.323.762.72 1.305 1.075 1.787.114.156.224.305.325.454a.667.667 0 0 0 .488.316 3.043 3.043 0 0 0-.417 1.13c-.458.124-.805.676-.805 1.341 0 .59.276 1.096.66 1.286l-.217 6.446a13.266 13.266 0 0 1-5.491 1.18V6.922A4.924 4.924 0 0 0 7.63 2Zm-.514 6.574a.457.457 0 0 0-.11-.345.446.446 0 0 0-.149-.11L5.591 7.55a.304.304 0 0 0-.304.524l1.127.814a.444.444 0 0 0 .522-.003.456.456 0 0 0 .125-.136.456.456 0 0 0 .056-.175Zm-.11 7.395a.446.446 0 0 0 .092-.16h-.002a.456.456 0 0 0-.038-.359.445.445 0 0 0-.646-.138l-1.128.812a.304.304 0 0 0 .305.525l1.267-.57a.446.446 0 0 0 .15-.11ZM4.33 12.372l.484.166a.544.544 0 1 0 0-1.032l-.484.166a.37.37 0 0 0 0 .7Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.98 3.094A9.993 9.993 0 0 1 20.422 12a9.997 9.997 0 0 1-5.394 8.877l-.304-9.017v-.096a.403.403 0 0 0 .065-.038c.352-.211.595-.692.595-1.247 0-.066-.003-.132-.01-.198-.061-.575-.382-1.032-.795-1.144a2.988 2.988 0 0 0-.409-1.13.666.666 0 0 0 .496-.316c.101-.15.211-.3.326-.458.35-.481.745-1.022 1.066-1.768l.018-.042a.365.365 0 0 0-.044-.38.373.373 0 0 0-.566-.035c-.294.28-.607.457-.9.623-.34.194-.652.37-.874.674a.97.97 0 0 0-.583-.523c.51-.97 1.138-1.873 1.871-2.688Zm3.348 9.442.486-.166a.37.37 0 0 0 0-.7l-.486-.166a.545.545 0 1 0 0 1.032Zm-.708 4.122a.304.304 0 0 0 .084-.536l-1.127-.813a.443.443 0 0 0-.645.139.443.443 0 0 0 .202.628l1.268.57a.294.294 0 0 0 .218.012ZM15.985 8.23a.448.448 0 0 0-.11.345.444.444 0 0 0 .182.313.447.447 0 0 0 .521.002l1.128-.814a.304.304 0 0 0-.304-.524l-1.268.57a.445.445 0 0 0-.15.108Z" fill="currentColor"/>
<path d="M6.19 5.48A4.924 4.924 0 0 0 7.63 2H4.514A1.803 1.803 0 0 0 2.71 3.803v3.119a4.92 4.92 0 0 0 3.479-1.443Zm6.286 5.224-.507.466a.314.314 0 0 0-.09.152c-.033.134-.099.397-.152.647a.152.152 0 0 1-.152.115.152.152 0 0 1-.152-.115l-.162-.647a.304.304 0 0 0-.09-.152l-.506-.466a.151.151 0 0 1-.033-.175.153.153 0 0 1 .156-.086l.76.103h.042l.06-.007.7-.096a.153.153 0 0 1 .153.085.152.152 0 0 1-.035.176m.76-.17a1.82 1.82 0 0 1 .271-.927.608.608 0 0 0 .05-.503l-.036.032a.888.888 0 0 1-1.086.009c0 .313-.286.572-.66.618a.988.988 0 0 1-.118 0c-.427 0-.776-.28-.776-.626a.888.888 0 0 1-1.086-.009.65.65 0 0 1-.114-.12.596.596 0 0 0-.034.628c.147.277.224.585.223.898 0 .327-.087.648-.253.93a.609.609 0 0 0 .056.689c.437.525 1.135.961 1.803 1.02h.165c.773 0 1.38-.482 1.813-1.114a.599.599 0 0 0 .026-.626 1.892 1.892 0 0 1-.228-.897" fill="currentColor"/>
</svg>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M22 12c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2s10 4.477 10 10Zm-8.293-4.547c1.539.117 2.84 1.137 2.84 1.137s1.453 2.11 1.71 6.25c-1.464 1.691-3.69 1.703-3.69 1.703l-.466-.621a5.672 5.672 0 0 0 2.454-1.652c-.922.699-2.309 1.422-4.547 1.422-2.239 0-3.63-.727-4.547-1.422a5.672 5.672 0 0 0 2.453 1.652l-.465.621s-2.226-.012-3.691-1.703c.25-4.14 1.703-6.25 1.703-6.25s1.226-.984 2.84-1.137l.136.278c-1.27.285-2.027.828-2.695 1.425 1.149-.586 2.285-1.136 4.262-1.136 1.976 0 3.113.55 4.262 1.136-.668-.597-1.305-1.086-2.696-1.425l.137-.278Zm-4.55 5.114c0 .628.444 1.136.995 1.136.551 0 .996-.508.996-1.136 0-.63-.445-1.137-.996-1.137-.55 0-.996.508-.996 1.137Zm3.694 0c0 .628.446 1.136.997 1.136.546 0 .996-.508.996-1.136 0-.63-.446-1.137-.996-1.137-.551 0-.997.508-.997 1.137Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M22.122 12.061C22.122 6.505 17.618 2 12.062 2 6.504 2 2 6.505 2 12.061c0 5.022 3.68 9.184 8.49 9.939v-7.03H7.933v-2.91h2.555V9.845c0-2.522 1.502-3.915 3.8-3.915 1.101 0 2.252.197 2.252.197v2.476h-1.268c-1.25 0-1.64.775-1.64 1.57v1.888h2.79l-.445 2.908h-2.345V22c4.81-.755 8.49-4.917 8.49-9.939Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.005 2c-5.525 0-10 4.475-10 10a9.994 9.994 0 0 0 6.837 9.488c.5.087.688-.213.688-.476 0-.237-.013-1.024-.013-1.862-2.512.463-3.162-.612-3.362-1.175-.113-.288-.6-1.175-1.025-1.413-.35-.187-.85-.65-.013-.662.788-.013 1.35.725 1.538 1.025.9 1.512 2.337 1.087 2.912.825.088-.65.35-1.087.638-1.337-2.225-.25-4.55-1.113-4.55-4.938 0-1.088.387-1.987 1.025-2.688-.1-.25-.45-1.275.1-2.65 0 0 .837-.262 2.75 1.026a9.28 9.28 0 0 1 2.5-.338c.85 0 1.7.112 2.5.337 1.912-1.3 2.75-1.024 2.75-1.024.55 1.375.2 2.4.1 2.65.637.7 1.025 1.587 1.025 2.687 0 3.838-2.338 4.688-4.563 4.938.363.312.675.912.675 1.85 0 1.337-.012 2.412-.012 2.75 0 .262.187.574.687.474A10.016 10.016 0 0 0 22.005 12c0-5.525-4.475-10-10-10Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2c5.52 0 10 4.48 10 10s-4.48 10-10 10S2 17.52 2 12 6.48 2 12 2ZM8.874 17.62V9.81H6.277v7.81h2.597Zm9.36 0v-4.478c0-2.4-1.281-3.515-2.989-3.515-1.377 0-1.994.757-2.34 1.29V9.81H10.31c.034.732 0 7.809 0 7.809h2.596v-4.361c0-.234.016-.467.085-.634.188-.466.615-.95 1.332-.95.939 0 1.315.717 1.315 1.767v4.178h2.596ZM7.593 6.045c-.888 0-1.469.584-1.469 1.35 0 .749.563 1.349 1.435 1.349h.016c.906 0 1.47-.6 1.47-1.35-.018-.765-.564-1.35-1.452-1.35Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 2C6.478 2 2 6.477 2 12s4.478 10 10 10c5.523 0 10-4.477 10-10S17.523 2 12 2Zm5.673 6.628h-.455c-.17 0-.409.244-.409.4v5.662c0 .156.24.369.409.369h.455v1.344h-4.127v-1.344h.864V9.108h-.043l-2.017 7.295h-1.562L8.797 9.108h-.05v5.951h.863v1.344H6.155v-1.344h.442c.182 0 .421-.213.421-.37v-5.66c0-.156-.239-.4-.421-.4h-.442V7.284h4.32l1.42 5.28h.038l1.432-5.28h4.308v1.344Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="opensea_filled_svg__a" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="2" width="20" height="20">
<path d="M22 2H2v20h20V2Z" fill="#fff"/>
</mask>
<g mask="url(#opensea_filled_svg__a)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.037 2.035c5.52 0 10 4.48 10 10s-4.48 10-10 10-10-4.48-10-10 4.48-10 10-10Zm2.732 7.245.053.068.075.098c.02.04.06.081.08.142.036.053.068.106.099.16l.026.045c.031.053.063.107.099.16.02.06.06.121.08.182.082.162.143.325.163.507.02.04.02.081.02.101.02.04.02.102.02.162.02.183 0 .345-.02.527-.007.03-.015.058-.023.085l-.015.054a2.655 2.655 0 0 0-.023.084c-.02.061-.04.142-.08.223-.062.142-.143.284-.224.426-.02.04-.06.101-.101.162-.04.061-.081.102-.101.162-.041.061-.102.122-.142.183-.04.06-.081.121-.142.182-.061.081-.142.162-.203.243-.04.041-.081.102-.142.142-.04.04-.08.102-.142.142-.06.061-.121.122-.182.162l-.122.102c-.02.02-.04.02-.06.02h-.893v1.135h1.115c.244 0 .487-.08.67-.243.06-.06.344-.304.688-.669.02-.02.02-.02.041-.02l3.081-.892c.122-.06.162-.02.162.04v.65c0 .04-.02.06-.06.08-.203.081-.913.405-1.197.81-.75 1.035-1.317 2.514-2.574 2.514h-5.29a3.396 3.396 0 0 1-3.385-3.405v-.06c0-.041.04-.082.08-.082h2.98c.061 0 .102.061.102.101-.02.183.02.386.101.568.182.365.547.568.933.568h1.459v-1.135h-1.44a.091.091 0 0 1-.08-.142.28.28 0 0 0 .06-.082c.142-.202.325-.486.527-.83.142-.224.264-.487.365-.73.02-.04.04-.081.061-.142.02-.081.061-.162.081-.223l.061-.183c.04-.202.06-.425.06-.668 0-.082 0-.183-.02-.284 0-.045-.003-.089-.008-.133l-.003-.038a1.319 1.319 0 0 1-.009-.133c0-.081-.02-.183-.04-.264a2.866 2.866 0 0 0-.081-.405l-.02-.04c-.02-.082-.041-.183-.082-.264a7.58 7.58 0 0 0-.283-.811l-.122-.304a7.912 7.912 0 0 0-.182-.406c-.02-.06-.061-.1-.082-.162-.02-.06-.06-.121-.08-.182l-.061-.122-.183-.324c-.02-.04.02-.101.06-.081l1.116.304.142.04.162.041.06.02v-.669c0-.324.264-.588.568-.588.162 0 .304.061.406.163a.566.566 0 0 1 .162.405V7.5l.121.04s.02 0 .02.02c.021.021.061.062.122.102.04.04.081.081.142.122.102.08.243.203.385.324.04.04.081.06.102.101.182.163.385.365.588.588.06.061.1.122.162.183.06.06.101.142.162.202l.075.098Zm-7.88 3.105.041-.06 2.635-4.116c.041-.06.122-.06.163.02.446.994.81 2.21.648 2.98-.08.325-.284.75-.527 1.136a.442.442 0 0 1-.101.162c-.02.02-.04.04-.081.04H6.95c-.061-.02-.102-.101-.061-.162Z" fill="currentColor"/>
</g>
</svg>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2c5.52 0 10 4.48 10 10s-4.48 10-10 10S2 17.52 2 12 6.48 2 12 2Zm6.667 10c0-.807-.655-1.462-1.462-1.462a1.4 1.4 0 0 0-1.006.41c-.994-.714-2.374-1.182-3.895-1.24l.667-3.123 2.163.456a1.042 1.042 0 0 0 2.082-.047c0-.573-.467-1.04-1.04-1.04-.41 0-.76.233-.925.584l-2.42-.515a.291.291 0 0 0-.2.035.285.285 0 0 0-.116.164l-.737 3.486c-1.556.046-2.948.502-3.953 1.24a1.476 1.476 0 0 0-1.006-.41 1.463 1.463 0 0 0-.597 2.795c-.023.14-.035.293-.035.445 0 2.245 2.608 4.058 5.836 4.058s5.837-1.813 5.837-4.058c0-.152-.012-.293-.035-.433.48-.234.842-.748.842-1.345Zm-4.188 3.79c-.713.713-2.07.76-2.467.76-.398 0-1.766-.059-2.468-.76a.275.275 0 0 1 0-.386.275.275 0 0 1 .386 0c.444.444 1.403.608 2.093.608s1.638-.164 2.094-.609a.275.275 0 0 1 .386 0 .3.3 0 0 1-.024.386Zm-5.812-2.75c0-.572.467-1.04 1.04-1.04.574 0 1.042.468 1.042 1.04 0 .574-.468 1.042-1.041 1.042a1.043 1.043 0 0 1-1.041-1.041Zm5.625 1.042a1.043 1.043 0 0 1-1.04-1.041c0-.573.467-1.041 1.04-1.041.574 0 1.041.468 1.041 1.04 0 .574-.467 1.042-1.04 1.042Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2c5.52 0 10 4.48 10 10s-4.48 10-10 10S2 17.52 2 12 6.48 2 12 2Zm1.598 13.51c.7 0 1.272.572 1.272 1.273 0 .7-.572 1.272-1.272 1.272-.7 0-1.273-.572-1.273-1.272V15.51h1.273ZM9.13 13.599c0-.7.572-1.273 1.272-1.273.7 0 1.273.572 1.273 1.273v3.185c0 .7-.572 1.272-1.273 1.272-.7 0-1.272-.572-1.272-1.272v-3.186Zm-.64 0c0 .7-.572 1.272-1.273 1.272-.7 0-1.272-.572-1.272-1.272 0-.7.572-1.273 1.272-1.273H8.49v1.273Zm8.293 1.272c.7 0 1.272-.572 1.272-1.272 0-.7-.572-1.273-1.272-1.273h-3.186c-.7 0-1.272.572-1.272 1.273 0 .7.572 1.272 1.273 1.272h3.185Zm0-3.195c.7 0 1.272-.572 1.272-1.273 0-.7-.572-1.272-1.272-1.272-.7 0-1.273.572-1.273 1.272v1.273h1.273Zm-1.913-1.273c0 .7-.572 1.273-1.272 1.273-.7 0-1.273-.572-1.273-1.273V7.217c0-.7.572-1.272 1.273-1.272.7 0 1.272.572 1.272 1.272v3.186Zm-4.467 1.273c.7 0 1.272-.572 1.272-1.273 0-.7-.572-1.272-1.273-1.272H7.217c-.7 0-1.272.572-1.272 1.272 0 .7.572 1.273 1.272 1.273h3.186Zm1.272-3.186V7.217c0-.7-.572-1.272-1.273-1.272-.7 0-1.272.572-1.272 1.272 0 .7.572 1.272 1.272 1.272h1.273Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M22.01 12c0 5.523-4.477 10-10 10s-10-4.477-10-10 4.477-10 10-10 10 4.477 10 10Zm-9.73-3.495a525.959 525.959 0 0 0-6.445 2.776c-.523.208-.797.412-.822.61-.042.337.38.47.953.65l.241.076c.564.184 1.323.398 1.718.407.358.008.757-.14 1.198-.443 3.01-2.031 4.564-3.058 4.661-3.08.069-.016.164-.036.229.022.064.057.058.166.051.195-.041.178-1.694 1.715-2.55 2.51-.267.248-.456.424-.494.464-.087.09-.175.175-.26.257-.524.505-.917.884.021 1.503.452.297.813.543 1.173.789.393.267.786.535 1.293.867.13.085.253.173.374.259.457.326.869.62 1.377.573.295-.027.6-.305.755-1.133.366-1.957 1.086-6.197 1.252-7.944a1.942 1.942 0 0 0-.019-.435.465.465 0 0 0-.157-.3c-.132-.107-.337-.13-.428-.128-.416.007-1.053.23-4.122 1.505Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.005 22c5.523 0 10-4.477 10-10s-4.477-10-10-10-10 4.477-10 10 4.477 10 10 10Zm5.011-12.322c.483-.35.894-.774 1.234-1.27a4.938 4.938 0 0 1-1.416.38 2.39 2.39 0 0 0 1.081-1.355 4.823 4.823 0 0 1-1.56.593 2.371 2.371 0 0 0-1.798-.776c-.68 0-1.26.24-1.74.72a2.37 2.37 0 0 0-.72 1.739c0 .182.021.37.062.563a6.855 6.855 0 0 1-2.83-.757 6.971 6.971 0 0 1-2.241-1.816 2.4 2.4 0 0 0-.335 1.24 2.456 2.456 0 0 0 1.096 2.048 2.44 2.44 0 0 1-1.112-.312v.031c0 .594.187 1.115.56 1.564.373.45.844.732 1.412.849a2.542 2.542 0 0 1-.647.084c-.142 0-.297-.013-.464-.038.157.492.446.897.868 1.214a2.4 2.4 0 0 0 1.431.49 4.816 4.816 0 0 1-3.053 1.051c-.218 0-.416-.01-.594-.03a6.83 6.83 0 0 0 3.777 1.104 7.19 7.19 0 0 0 2.459-.415c.766-.277 1.421-.647 1.964-1.112a7.434 7.434 0 0 0 1.405-1.602 7.138 7.138 0 0 0 .88-1.892 6.983 6.983 0 0 0 .282-2.295Z" fill="currentColor"/>
</svg>
import type { UserInfo, CustomAbis, PublicTags, AddressTags, TransactionTags, ApiKeys, WatchlistAddress } from 'types/api/account'; import type {
UserInfo,
CustomAbis,
PublicTags,
AddressTags,
TransactionTags,
ApiKeys,
WatchlistAddress,
VerifiedAddressResponse,
TokenInfoApplicationConfig,
TokenInfoApplications,
} from 'types/api/account';
import type { import type {
Address, Address,
AddressCounters, AddressCounters,
...@@ -36,6 +47,7 @@ import type { ...@@ -36,6 +47,7 @@ import type {
TokenInventoryResponse, TokenInventoryResponse,
TokenInstance, TokenInstance,
TokenInstanceTransfersCount, TokenInstanceTransfersCount,
TokenVerifiedInfo,
} from 'types/api/token'; } from 'types/api/token';
import type { TokensResponse, TokensFilters, TokenInstanceTransferResponse } from 'types/api/tokens'; import type { TokensResponse, TokensFilters, TokenInstanceTransferResponse } from 'types/api/tokens';
import type { TokenTransferResponse, TokenTransferFilters } from 'types/api/tokenTransfer'; import type { TokenTransferResponse, TokenTransferFilters } from 'types/api/tokenTransfer';
...@@ -63,6 +75,9 @@ export const RESOURCES = { ...@@ -63,6 +75,9 @@ export const RESOURCES = {
user_info: { user_info: {
path: '/api/account/v1/user/info', path: '/api/account/v1/user/info',
}, },
email_resend: {
path: '/api/account/v1/email/resend',
},
custom_abi: { custom_abi: {
path: '/api/account/v1/user/custom_abis/:id?', path: '/api/account/v1/user/custom_abis/:id?',
pathParams: [ 'id' as const ], pathParams: [ 'id' as const ],
...@@ -88,6 +103,35 @@ export const RESOURCES = { ...@@ -88,6 +103,35 @@ export const RESOURCES = {
pathParams: [ 'id' as const ], pathParams: [ 'id' as const ],
}, },
// ACCOUNT: ADDRESS VERIFICATION & TOKEN INFO
address_verification: {
path: '/api/v1/chains/:chainId/verified-addresses:type',
pathParams: [ 'chainId' as const, 'type' as const ],
endpoint: appConfig.contractInfoApi.endpoint,
basePath: appConfig.contractInfoApi.basePath,
},
verified_addresses: {
path: '/api/v1/chains/:chainId/verified-addresses',
pathParams: [ 'chainId' as const ],
endpoint: appConfig.contractInfoApi.endpoint,
basePath: appConfig.contractInfoApi.basePath,
},
token_info_applications_config: {
path: '/api/v1/chains/:chainId/token-info-submissions/selectors',
pathParams: [ 'chainId' as const ],
endpoint: appConfig.adminServiceApi.endpoint,
basePath: appConfig.adminServiceApi.basePath,
},
token_info_applications: {
path: '/api/v1/chains/:chainId/token-info-submissions/:id?',
pathParams: [ 'chainId' as const, 'id' as const ],
endpoint: appConfig.adminServiceApi.endpoint,
basePath: appConfig.adminServiceApi.basePath,
},
// STATS // STATS
stats_counters: { stats_counters: {
path: '/api/v1/counters', path: '/api/v1/counters',
...@@ -309,6 +353,12 @@ export const RESOURCES = { ...@@ -309,6 +353,12 @@ export const RESOURCES = {
path: '/api/v2/tokens/:hash', path: '/api/v2/tokens/:hash',
pathParams: [ 'hash' as const ], pathParams: [ 'hash' as const ],
}, },
token_verified_info: {
path: '/api/v1/chains/:chainId/token-infos/:hash',
pathParams: [ 'chainId' as const, 'hash' as const ],
endpoint: appConfig.contractInfoApi.endpoint,
basePath: appConfig.contractInfoApi.basePath,
},
token_counters: { token_counters: {
path: '/api/v2/tokens/:hash/counters', path: '/api/v2/tokens/:hash/counters',
pathParams: [ 'hash' as const ], pathParams: [ 'hash' as const ],
...@@ -524,6 +574,9 @@ Q extends 'private_tags_address' ? AddressTags : ...@@ -524,6 +574,9 @@ Q extends 'private_tags_address' ? AddressTags :
Q extends 'private_tags_tx' ? TransactionTags : Q extends 'private_tags_tx' ? TransactionTags :
Q extends 'api_keys' ? ApiKeys : Q extends 'api_keys' ? ApiKeys :
Q extends 'watchlist' ? Array<WatchlistAddress> : Q extends 'watchlist' ? Array<WatchlistAddress> :
Q extends 'verified_addresses' ? VerifiedAddressResponse :
Q extends 'token_info_applications_config' ? TokenInfoApplicationConfig :
Q extends 'token_info_applications' ? TokenInfoApplications :
Q extends 'homepage_stats' ? HomeStats : Q extends 'homepage_stats' ? HomeStats :
Q extends 'homepage_chart_txs' ? ChartTransactionResponse : Q extends 'homepage_chart_txs' ? ChartTransactionResponse :
Q extends 'homepage_chart_market' ? ChartMarketResponse : Q extends 'homepage_chart_market' ? ChartMarketResponse :
...@@ -561,6 +614,7 @@ Q extends 'address_logs' ? LogsResponseAddress : ...@@ -561,6 +614,7 @@ Q extends 'address_logs' ? LogsResponseAddress :
Q extends 'address_tokens' ? AddressTokensResponse : Q extends 'address_tokens' ? AddressTokensResponse :
Q extends 'address_withdrawals' ? AddressWithdrawalsResponse : Q extends 'address_withdrawals' ? AddressWithdrawalsResponse :
Q extends 'token' ? TokenInfo : Q extends 'token' ? TokenInfo :
Q extends 'token_verified_info' ? TokenVerifiedInfo :
Q extends 'token_counters' ? TokenCounters : Q extends 'token_counters' ? TokenCounters :
Q extends 'token_transfers' ? TokenTransferResponse : Q extends 'token_transfers' ? TokenTransferResponse :
Q extends 'token_holders' ? TokenHolders : Q extends 'token_holders' ? TokenHolders :
......
import React from 'react'; import React from 'react';
import appConfig from 'configs/app/config'; import isNeedProxy from 'lib/api/isNeedProxy';
import type { Params as FetchParams } from 'lib/hooks/useFetch'; import type { Params as FetchParams } from 'lib/hooks/useFetch';
import useFetch from 'lib/hooks/useFetch'; import useFetch from 'lib/hooks/useFetch';
...@@ -27,7 +27,7 @@ export default function useApiFetch() { ...@@ -27,7 +27,7 @@ export default function useApiFetch() {
url, url,
{ {
credentials: 'include', credentials: 'include',
...(resource.endpoint && appConfig.host === 'localhost' ? { ...(resource.endpoint && isNeedProxy() ? {
headers: { headers: {
'x-endpoint': resource.endpoint, 'x-endpoint': resource.endpoint,
}, },
......
...@@ -33,6 +33,8 @@ export function app(): CspDev.DirectiveDescriptor { ...@@ -33,6 +33,8 @@ export function app(): CspDev.DirectiveDescriptor {
appConfig.api.socket, appConfig.api.socket,
appConfig.statsApi.endpoint, appConfig.statsApi.endpoint,
appConfig.visualizeApi.endpoint, appConfig.visualizeApi.endpoint,
appConfig.contractInfoApi.endpoint,
appConfig.adminServiceApi.endpoint,
// chain RPC server // chain RPC server
appConfig.network.rpcUrl, appConfig.network.rpcUrl,
......
import getErrorCause from './getErrorCause'; import getErrorCause from './getErrorCause';
export default function getErrorStatusCode(error: Error | undefined): number | undefined { export default function getErrorCauseStatusCode(error: Error | undefined): number | undefined {
const cause = getErrorCause(error); const cause = getErrorCause(error);
return cause && 'status' in cause && typeof cause.status === 'number' ? cause.status : undefined; return cause && 'status' in cause && typeof cause.status === 'number' ? cause.status : undefined;
} }
export default function getErrorObj(error: unknown) {
if (typeof error !== 'object') {
return;
}
if (Array.isArray(error)) {
return;
}
if (error === null) {
return;
}
return error;
}
import getErrorObj from './getErrorObj';
export default function getErrorObjPayload<Payload extends object>(error: unknown): Payload | undefined {
const errorObj = getErrorObj(error);
if (!errorObj || !('payload' in errorObj)) {
return;
}
if (typeof errorObj.payload !== 'object') {
return;
}
if (errorObj === null) {
return;
}
if (Array.isArray(errorObj)) {
return;
}
return errorObj.payload as Payload;
}
import getErrorObj from './getErrorObj';
export default function getErrorObjStatusCode(error: unknown) {
const errorObj = getErrorObj(error);
if (!errorObj || !('status' in errorObj) || typeof errorObj.status !== 'number') {
return;
}
return errorObj.status;
}
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import type { Route } from 'nextjs-routes';
import React from 'react'; import React from 'react';
import type { NavItemInternal, NavItem, NavGroupItem } from 'types/client/navigation-items';
import appConfig from 'configs/app/config'; import appConfig from 'configs/app/config';
import abiIcon from 'icons/ABI.svg'; import abiIcon from 'icons/ABI.svg';
import apiKeysIcon from 'icons/API.svg'; import apiKeysIcon from 'icons/API.svg';
...@@ -27,28 +28,6 @@ import verifiedIcon from 'icons/verified.svg'; ...@@ -27,28 +28,6 @@ import verifiedIcon from 'icons/verified.svg';
import watchlistIcon from 'icons/watchlist.svg'; import watchlistIcon from 'icons/watchlist.svg';
import { rightLineArrow } from 'lib/html-entities'; import { rightLineArrow } from 'lib/html-entities';
type NavItemCommon = {
text: string;
icon: React.FunctionComponent<React.SVGAttributes<SVGElement>>;
}
type NavItemInternal = NavItemCommon & {
nextRoute: Route;
isActive?: boolean;
isNewUi?: boolean;
}
type NavItemExternal = NavItemCommon & {
url: string;
}
export type NavItem = NavItemInternal | NavItemExternal
export type NavGroupItem = NavItemCommon & {
isActive?: boolean;
subItems: Array<NavItem> | Array<Array<NavItem>>;
}
interface ReturnType { interface ReturnType {
mainNavItems: Array<NavItem | NavGroupItem>; mainNavItems: Array<NavItem | NavGroupItem>;
accountNavItems: Array<NavItem>; accountNavItems: Array<NavItem>;
...@@ -78,41 +57,38 @@ export default function useNavItems(): ReturnType { ...@@ -78,41 +57,38 @@ export default function useNavItems(): ReturnType {
nextRoute: { pathname: '/accounts' as const }, nextRoute: { pathname: '/accounts' as const },
icon: topAccountsIcon, icon: topAccountsIcon,
isActive: pathname === '/accounts', isActive: pathname === '/accounts',
isNewUi: true,
}; };
const blocks = { const blocks = {
text: 'Blocks', text: 'Blocks',
nextRoute: { pathname: '/blocks' as const }, nextRoute: { pathname: '/blocks' as const },
icon: blocksIcon, icon: blocksIcon,
isActive: pathname === '/blocks' || pathname === '/block/[height]', isActive: pathname === '/blocks' || pathname === '/block/[height]',
isNewUi: true,
}; };
const txs = { const txs = {
text: 'Transactions', text: 'Transactions',
nextRoute: { pathname: '/txs' as const }, nextRoute: { pathname: '/txs' as const },
icon: transactionsIcon, icon: transactionsIcon,
isActive: pathname === '/txs' || pathname === '/tx/[hash]', isActive: pathname === '/txs' || pathname === '/tx/[hash]',
isNewUi: true,
}; };
const verifiedContracts = const verifiedContracts =
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
{ text: 'Verified contracts', nextRoute: { pathname: '/verified-contracts' as const }, icon: verifiedIcon, isActive: pathname === '/verified-contracts', isNewUi: true }; { text: 'Verified contracts', nextRoute: { pathname: '/verified-contracts' as const }, icon: verifiedIcon, isActive: pathname === '/verified-contracts' };
if (appConfig.L2.isL2Network) { if (appConfig.L2.isL2Network) {
blockchainNavItems = [ blockchainNavItems = [
[ [
txs, txs,
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
{ text: `Deposits (L1${ rightLineArrow }L2)`, nextRoute: { pathname: '/l2-deposits' as const }, icon: depositsIcon, isActive: pathname === '/l2-deposits', isNewUi: true }, { text: `Deposits (L1${ rightLineArrow }L2)`, nextRoute: { pathname: '/l2-deposits' as const }, icon: depositsIcon, isActive: pathname === '/l2-deposits' },
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
{ text: `Withdrawals (L2${ rightLineArrow }L1)`, nextRoute: { pathname: '/l2-withdrawals' as const }, icon: withdrawalsIcon, isActive: pathname === '/l2-withdrawals', isNewUi: true }, { text: `Withdrawals (L2${ rightLineArrow }L1)`, nextRoute: { pathname: '/l2-withdrawals' as const }, icon: withdrawalsIcon, isActive: pathname === '/l2-withdrawals' },
], ],
[ [
blocks, blocks,
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
{ text: 'Txn batches', nextRoute: { pathname: '/l2-txn-batches' as const }, icon: txnBatchIcon, isActive: pathname === '/l2-txn-batches', isNewUi: true }, { text: 'Txn batches', nextRoute: { pathname: '/l2-txn-batches' as const }, icon: txnBatchIcon, isActive: pathname === '/l2-txn-batches' },
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
{ text: 'Output roots', nextRoute: { pathname: '/l2-output-roots' as const }, icon: outputRootsIcon, isActive: pathname === '/l2-output-roots', isNewUi: true }, { text: 'Output roots', nextRoute: { pathname: '/l2-output-roots' as const }, icon: outputRootsIcon, isActive: pathname === '/l2-output-roots' },
], ],
[ [
topAccounts, topAccounts,
...@@ -130,25 +106,22 @@ export default function useNavItems(): ReturnType { ...@@ -130,25 +106,22 @@ export default function useNavItems(): ReturnType {
nextRoute: { pathname: '/withdrawals' as const }, nextRoute: { pathname: '/withdrawals' as const },
icon: withdrawalsIcon, icon: withdrawalsIcon,
isActive: pathname === '/withdrawals', isActive: pathname === '/withdrawals',
isNewUi: true,
}, },
].filter(Boolean); ].filter(Boolean);
} }
const otherNavItems: Array<NavItem> = [ const apiNavItems: Array<NavItem> = [
hasAPIDocs ? { hasAPIDocs ? {
text: 'REST API', text: 'REST API',
nextRoute: { pathname: '/api-docs' as const }, nextRoute: { pathname: '/api-docs' as const },
icon: apiDocsIcon, icon: apiDocsIcon,
isActive: pathname === '/api-docs', isActive: pathname === '/api-docs',
isNewUi: true,
} : null, } : null,
{ {
text: 'GraphQL', text: 'GraphQL',
nextRoute: { pathname: '/graphiql' as const }, nextRoute: { pathname: '/graphiql' as const },
icon: graphQLIcon, icon: graphQLIcon,
isActive: pathname === '/graphiql', isActive: pathname === '/graphiql',
isNewUi: true,
}, },
{ {
text: 'RPC API', text: 'RPC API',
...@@ -167,7 +140,6 @@ export default function useNavItems(): ReturnType { ...@@ -167,7 +140,6 @@ export default function useNavItems(): ReturnType {
text: 'Blockchain', text: 'Blockchain',
icon: globeIcon, icon: globeIcon,
isActive: blockchainNavItems.flat().some(item => isInternalItem(item) && item.isActive), isActive: blockchainNavItems.flat().some(item => isInternalItem(item) && item.isActive),
isNewUi: true,
subItems: blockchainNavItems, subItems: blockchainNavItems,
}, },
{ {
...@@ -175,24 +147,24 @@ export default function useNavItems(): ReturnType { ...@@ -175,24 +147,24 @@ export default function useNavItems(): ReturnType {
nextRoute: { pathname: '/tokens' as const }, nextRoute: { pathname: '/tokens' as const },
icon: tokensIcon, icon: tokensIcon,
isActive: pathname.startsWith('/token'), isActive: pathname.startsWith('/token'),
isNewUi: true,
}, },
isMarketplaceAvailable ? { isMarketplaceAvailable ? {
text: 'Apps', text: 'Apps',
nextRoute: { pathname: '/apps' as const }, nextRoute: { pathname: '/apps' as const },
icon: appsIcon, icon: appsIcon,
isActive: pathname.startsWith('/app'), isActive: pathname.startsWith('/app'),
isNewUi: true,
} : null, } : null,
{ text: 'Charts & stats', nextRoute: { pathname: '/stats' as const }, icon: statsIcon, isActive: pathname === '/stats', isNewUi: true }, { text: 'Charts & stats', nextRoute: { pathname: '/stats' as const }, icon: statsIcon, isActive: pathname === '/stats' },
// there should be custom site sections like Stats, Faucet, More, etc but never an 'other' {
// examples https://explorer-edgenet.polygon.technology/ and https://explorer.celo.org/ text: 'API',
// at this stage custom menu items is under development, we will implement it later icon: apiDocsIcon,
otherNavItems.length > 0 ? { isActive: apiNavItems.some(item => isInternalItem(item) && item.isActive),
subItems: apiNavItems,
},
appConfig.otherLinks.length > 0 ? {
text: 'Other', text: 'Other',
icon: gearIcon, icon: gearIcon,
isActive: otherNavItems.some(item => isInternalItem(item) && item.isActive), subItems: appConfig.otherLinks,
subItems: otherNavItems,
} : null, } : null,
].filter(Boolean) as Array<NavItem | NavGroupItem>; ].filter(Boolean) as Array<NavItem | NavGroupItem>;
...@@ -202,42 +174,42 @@ export default function useNavItems(): ReturnType { ...@@ -202,42 +174,42 @@ export default function useNavItems(): ReturnType {
nextRoute: { pathname: '/account/watchlist' as const }, nextRoute: { pathname: '/account/watchlist' as const },
icon: watchlistIcon, icon: watchlistIcon,
isActive: pathname === '/account/watchlist', isActive: pathname === '/account/watchlist',
isNewUi: true,
}, },
{ {
text: 'Private tags', text: 'Private tags',
nextRoute: { pathname: '/account/tag_address' as const }, nextRoute: { pathname: '/account/tag_address' as const },
icon: privateTagIcon, icon: privateTagIcon,
isActive: pathname === '/account/tag_address', isActive: pathname === '/account/tag_address',
isNewUi: true,
}, },
{ {
text: 'Public tags', text: 'Public tags',
nextRoute: { pathname: '/account/public_tags_request' as const }, nextRoute: { pathname: '/account/public_tags_request' as const },
icon: publicTagIcon, isActive: pathname === '/account/public_tags_request', icon: publicTagIcon, isActive: pathname === '/account/public_tags_request',
isNewUi: true,
}, },
{ {
text: 'API keys', text: 'API keys',
nextRoute: { pathname: '/account/api_key' as const }, nextRoute: { pathname: '/account/api_key' as const },
icon: apiKeysIcon, isActive: pathname === '/account/api_key', icon: apiKeysIcon, isActive: pathname === '/account/api_key',
isNewUi: true,
}, },
{ {
text: 'Custom ABI', text: 'Custom ABI',
nextRoute: { pathname: '/account/custom_abi' as const }, nextRoute: { pathname: '/account/custom_abi' as const },
icon: abiIcon, icon: abiIcon,
isActive: pathname === '/account/custom_abi', isActive: pathname === '/account/custom_abi',
isNewUi: true,
}, },
]; appConfig.contractInfoApi.endpoint && appConfig.adminServiceApi.endpoint && {
text: 'Verified addrs',
nextRoute: { pathname: '/account/verified_addresses' as const },
icon: verifiedIcon,
isActive: pathname === '/account/verified_addresses',
},
].filter(Boolean);
const profileItem = { const profileItem = {
text: 'My profile', text: 'My profile',
nextRoute: { pathname: '/auth/profile' as const }, nextRoute: { pathname: '/auth/profile' as const },
icon: profileIcon, icon: profileIcon,
isActive: pathname === '/auth/profile', isActive: pathname === '/auth/profile',
isNewUi: true,
}; };
return { mainNavItems, accountNavItems, profileItem }; return { mainNavItems, accountNavItems, profileItem };
......
import { useQueryClient } from '@tanstack/react-query';
import React from 'react';
import type { UserInfo } from 'types/api/account';
import { resourceKey } from 'lib/api/resources';
import useLoginUrl from 'lib/hooks/useLoginUrl';
export default function useRedirectIfNotAuth() {
const queryClient = useQueryClient();
const profileData = queryClient.getQueryData<UserInfo>([ resourceKey('user_info') ]);
const isAuth = Boolean(profileData);
const loginUrl = useLoginUrl();
return React.useCallback(() => {
if (!isAuth) {
window.location.assign(loginUrl);
return true;
}
return false;
}, [ isAuth, loginUrl ]);
}
import appConfig from 'configs/app/config';
import { getServerSideProps as base } from '../getServerSideProps';
export const getServerSideProps: typeof base = async(...args) => {
if (!appConfig.isAccountSupported) {
return {
notFound: true,
};
}
return base(...args);
};
export const getServerSidePropsForVerifiedAddresses: typeof base = async(...args) => {
if (!appConfig.isAccountSupported || !appConfig.adminServiceApi.endpoint || !appConfig.contractInfoApi.endpoint) {
return {
notFound: true,
};
}
return base(...args);
};
export default function shortenString(string: string | null) {
if (!string) {
return '';
}
if (string.length <= 7) {
return string;
}
return string.slice(0, 4) + '...' + string.slice(-4);
}
export const EMAIL_REGEXP = /^[\w.%+-]+@[a-zA-Z\d-]+(?:\.[a-zA-Z\d-]+)+$/; export const EMAIL_REGEXP = /^[\w.%+-]+@[a-zA-Z\d-]+(?:\.[a-zA-Z\d-]+)+$/;
export const validator = (value: string) => EMAIL_REGEXP.test(value) ? true : 'Invalid email';
export const SIGNATURE_REGEXP = /^0x[a-fA-F\d]{130}$/;
export const validator = (value: string | undefined) => {
if (!value) {
return true;
}
try {
new URL(value);
return true;
} catch (error) {
return 'Incorrect URL';
}
};
import type { TokenInfoApplication, TokenInfoApplications, VerifiedAddress, VerifiedAddressResponse } from 'types/api/account';
import type { AddressValidationResponseSuccess } from 'ui/addressVerification/types';
export const SIGNATURE = '0x96491e0cd1b99c14951552361b7f6ff64f41651b5d1c12501914342c8a6847e21e08726c3505e11ba2af9a40ac0b05c8d113e7fd1f74594224b9c7276ebb3a661b';
export const VERIFIED_ADDRESS: Record<string, VerifiedAddress> = {
NEW_ITEM: {
userId: '1',
chainId: '99',
contractAddress: '0xF822070D07067D1519490dBf49448a7E30EE9ea5',
verifiedDate: '2022-09-01',
metadata: {
tokenName: 'Test Token',
tokenSymbol: 'TT',
},
},
ITEM_1: {
userId: '1',
chainId: '99',
contractAddress: '0xd0e3010d1ecdbd17aae178b2bf36eb413d8a7441',
verifiedDate: '2022-08-01',
metadata: {
tokenName: 'My Token',
tokenSymbol: 'MYT',
},
},
ITEM_2: {
userId: '1',
chainId: '99',
contractAddress: '0xa8FCe579a11E551635b9c9CB915BEcd873C51254',
verifiedDate: '2022-09-23',
metadata: {
tokenName: 'Cat Token',
tokenSymbol: 'CATT',
},
},
};
export const ADDRESS_CHECK_RESPONSE = {
SUCCESS: {
status: 'SUCCESS',
result: {
// eslint-disable-next-line max-len
signingMessage: '[eth-goerli.blockscout.com] [2023-04-18 18:47:40] I, hereby verify that I am the owner/creator of the address [0xf822070d07067d1519490dbf49448a7e30ee9ea5]',
contractCreator: '0xd0e3010d1ecdbd17aae178b2bf36eb413d8a7441',
contractOwner: '0xa8FCe579a11E551635b9c9CB915BEcd873C51254',
},
},
SOURCE_CODE_NOT_VERIFIED_ERROR: {
status: 'SOURCE_CODE_NOT_VERIFIED_ERROR',
},
};
export const ADDRESS_VERIFY_RESPONSE: Record<string, AddressValidationResponseSuccess> = {
SUCCESS: {
status: 'SUCCESS',
result: {
verifiedAddress: VERIFIED_ADDRESS.NEW_ITEM,
},
},
INVALID_SIGNER_ERROR: {
status: 'INVALID_SIGNER_ERROR',
invalidSigner: {
signer: '0xF822070D07067D1519490dBf49448a7E30EE9ea5',
},
},
};
export const VERIFIED_ADDRESS_RESPONSE: Record<string, VerifiedAddressResponse> = {
DEFAULT: {
verifiedAddresses: [
VERIFIED_ADDRESS.ITEM_1,
VERIFIED_ADDRESS.ITEM_2,
],
},
};
export const TOKEN_INFO_APPLICATION_BASE = {
id: '1',
tokenAddress: VERIFIED_ADDRESS.ITEM_1.contractAddress,
status: 'APPROVED',
updatedAt: '2022-11-08 12:47:10.149148Z',
requesterName: 'Tom',
requesterEmail: 'tom@example.com',
projectName: 'My project',
projectWebsite: 'http://example.com',
projectEmail: 'token@example.com',
iconUrl: 'https://placekitten.com/100',
projectDescription: 'description',
projectSector: 'DeFi',
comment: '',
docs: 'https://example.com/docs',
github: 'https://github.com',
telegram: 'https://telegram.com',
linkedin: 'https://linkedin.com',
discord: 'https://discord.com',
slack: 'https://slack.com',
twitter: 'https://twitter.com',
openSea: 'https://opensea.com',
facebook: 'https://facebook.com',
medium: 'https://medium.com',
reddit: 'https://reddit.com',
support: 'support@example.com',
coinMarketCapTicker: 'https://coinmarketcap.com',
coinGeckoTicker: 'https://coingecko.com',
defiLlamaTicker: 'https://defillama.com',
};
export const TOKEN_INFO_APPLICATION: Record<string, TokenInfoApplication> = {
APPROVED: {
...TOKEN_INFO_APPLICATION_BASE,
tokenAddress: VERIFIED_ADDRESS.ITEM_1.contractAddress,
id: '1',
status: 'APPROVED',
updatedAt: '2022-11-08 12:47:10.149148Z',
},
IN_PROCESS: {
...TOKEN_INFO_APPLICATION_BASE,
tokenAddress: VERIFIED_ADDRESS.ITEM_2.contractAddress,
id: '2',
status: 'IN_PROCESS',
updatedAt: '2022-11-10 08:11:10.149148Z',
},
UPDATED_ITEM: {
...TOKEN_INFO_APPLICATION_BASE,
tokenAddress: VERIFIED_ADDRESS.ITEM_1.contractAddress,
id: '1',
status: 'IN_PROCESS',
updatedAt: '2022-11-11 05:11:10.149148Z',
},
};
export const TOKEN_INFO_APPLICATIONS_RESPONSE: Record<string, TokenInfoApplications> = {
DEFAULT: {
submissions: [
TOKEN_INFO_APPLICATION.APPROVED,
TOKEN_INFO_APPLICATION.IN_PROCESS,
],
},
FOR_UPDATE: {
submissions: [
{
...TOKEN_INFO_APPLICATION.APPROVED,
status: 'UPDATE_REQUIRED',
},
TOKEN_INFO_APPLICATION.IN_PROCESS,
],
},
};
export const TOKEN_INFO_FORM_CONFIG = {
projectSectors: [
'Infra & Dev tooling',
'DeFi',
'Data',
'Bridge',
'NFT',
'Payments',
'Faucet',
'DAO',
'Games',
'Wallet',
],
};
import type { AddressTokenBalance } from 'types/api/address'; import type { AddressTokenBalance } from 'types/api/address';
import * as tokens from 'mocks/tokens/tokenInfo'; import * as tokens from 'mocks/tokens/tokenInfo';
import * as tokenInstance from 'mocks/tokens/tokenInstance';
export const erc20a: AddressTokenBalance = { export const erc20a: AddressTokenBalance = {
token: tokens.tokenInfoERC20a, token: tokens.tokenInfoERC20a,
...@@ -59,24 +60,28 @@ export const erc721LongSymbol: AddressTokenBalance = { ...@@ -59,24 +60,28 @@ export const erc721LongSymbol: AddressTokenBalance = {
export const erc1155a: AddressTokenBalance = { export const erc1155a: AddressTokenBalance = {
token: tokens.tokenInfoERC1155a, token: tokens.tokenInfoERC1155a,
token_id: '42', token_id: '42',
token_instance: tokenInstance.base,
value: '24', value: '24',
}; };
export const erc1155b: AddressTokenBalance = { export const erc1155b: AddressTokenBalance = {
token: tokens.tokenInfoERC1155b, token: tokens.tokenInfoERC1155b,
token_id: '100010000000001', token_id: '100010000000001',
token_instance: tokenInstance.base,
value: '11', value: '11',
}; };
export const erc1155withoutName: AddressTokenBalance = { export const erc1155withoutName: AddressTokenBalance = {
token: tokens.tokenInfoERC1155WithoutName, token: tokens.tokenInfoERC1155WithoutName,
token_id: '64532245', token_id: '64532245',
token_instance: tokenInstance.base,
value: '42', value: '42',
}; };
export const erc1155LongId: AddressTokenBalance = { export const erc1155LongId: AddressTokenBalance = {
token: tokens.tokenInfoERC1155b, token: tokens.tokenInfoERC1155b,
token_id: '483200961027732618117991942553110860267520', token_id: '483200961027732618117991942553110860267520',
token_instance: tokenInstance.base,
value: '42', value: '42',
}; };
......
...@@ -9,6 +9,7 @@ export const tokenInfo: TokenInfo = { ...@@ -9,6 +9,7 @@ export const tokenInfo: TokenInfo = {
symbol: 'ARIA', symbol: 'ARIA',
type: 'ERC-20', type: 'ERC-20',
total_supply: '1235', total_supply: '1235',
icon_url: null,
}; };
export const tokenCounters: TokenCounters = { export const tokenCounters: TokenCounters = {
...@@ -25,6 +26,7 @@ export const tokenInfoERC20a: TokenInfo = { ...@@ -25,6 +26,7 @@ export const tokenInfoERC20a: TokenInfo = {
symbol: 'HyFi', symbol: 'HyFi',
total_supply: '369000000000000000000000000', total_supply: '369000000000000000000000000',
type: 'ERC-20', type: 'ERC-20',
icon_url: null,
}; };
export const tokenInfoERC20b: TokenInfo = { export const tokenInfoERC20b: TokenInfo = {
...@@ -36,6 +38,7 @@ export const tokenInfoERC20b: TokenInfo = { ...@@ -36,6 +38,7 @@ export const tokenInfoERC20b: TokenInfo = {
symbol: 'USDC', symbol: 'USDC',
total_supply: '900000000000000000000000000', total_supply: '900000000000000000000000000',
type: 'ERC-20', type: 'ERC-20',
icon_url: null,
}; };
export const tokenInfoERC20c: TokenInfo = { export const tokenInfoERC20c: TokenInfo = {
...@@ -47,6 +50,7 @@ export const tokenInfoERC20c: TokenInfo = { ...@@ -47,6 +50,7 @@ export const tokenInfoERC20c: TokenInfo = {
symbol: 'ETH', symbol: 'ETH',
total_supply: '1000000000000000000000000', total_supply: '1000000000000000000000000',
type: 'ERC-20', type: 'ERC-20',
icon_url: null,
}; };
export const tokenInfoERC20d: TokenInfo = { export const tokenInfoERC20d: TokenInfo = {
...@@ -58,6 +62,7 @@ export const tokenInfoERC20d: TokenInfo = { ...@@ -58,6 +62,7 @@ export const tokenInfoERC20d: TokenInfo = {
symbol: 'ZETA', symbol: 'ZETA',
total_supply: '2100000000000000000000000000', total_supply: '2100000000000000000000000000',
type: 'ERC-20', type: 'ERC-20',
icon_url: null,
}; };
export const tokenInfoERC20LongSymbol: TokenInfo = { export const tokenInfoERC20LongSymbol: TokenInfo = {
...@@ -69,6 +74,7 @@ export const tokenInfoERC20LongSymbol: TokenInfo = { ...@@ -69,6 +74,7 @@ export const tokenInfoERC20LongSymbol: TokenInfo = {
symbol: 'ipfs://QmUpFUfVKDCWeZQk5pvDFUxnpQP9N6eLSHhNUy49T1JVtY', symbol: 'ipfs://QmUpFUfVKDCWeZQk5pvDFUxnpQP9N6eLSHhNUy49T1JVtY',
total_supply: '2100000000000000000000000000', total_supply: '2100000000000000000000000000',
type: 'ERC-20', type: 'ERC-20',
icon_url: null,
}; };
export const tokenInfoERC721a: TokenInfo = { export const tokenInfoERC721a: TokenInfo = {
...@@ -80,6 +86,7 @@ export const tokenInfoERC721a: TokenInfo = { ...@@ -80,6 +86,7 @@ export const tokenInfoERC721a: TokenInfo = {
symbol: 'HYFI_ATHENA', symbol: 'HYFI_ATHENA',
total_supply: '105', total_supply: '105',
type: 'ERC-721', type: 'ERC-721',
icon_url: null,
}; };
export const tokenInfoERC721b: TokenInfo = { export const tokenInfoERC721b: TokenInfo = {
...@@ -91,6 +98,7 @@ export const tokenInfoERC721b: TokenInfo = { ...@@ -91,6 +98,7 @@ export const tokenInfoERC721b: TokenInfo = {
symbol: 'WOWG', symbol: 'WOWG',
total_supply: null, total_supply: null,
type: 'ERC-721', type: 'ERC-721',
icon_url: null,
}; };
export const tokenInfoERC721c: TokenInfo = { export const tokenInfoERC721c: TokenInfo = {
...@@ -102,6 +110,7 @@ export const tokenInfoERC721c: TokenInfo = { ...@@ -102,6 +110,7 @@ export const tokenInfoERC721c: TokenInfo = {
symbol: 'PUMA', symbol: 'PUMA',
total_supply: null, total_supply: null,
type: 'ERC-721', type: 'ERC-721',
icon_url: null,
}; };
export const tokenInfoERC721LongSymbol: TokenInfo = { export const tokenInfoERC721LongSymbol: TokenInfo = {
...@@ -113,6 +122,7 @@ export const tokenInfoERC721LongSymbol: TokenInfo = { ...@@ -113,6 +122,7 @@ export const tokenInfoERC721LongSymbol: TokenInfo = {
symbol: 'ipfs://QmUpFUfVKDCWeZQk5pvDFUxnpQP9N6eLSHhNUy49T1JVtY', symbol: 'ipfs://QmUpFUfVKDCWeZQk5pvDFUxnpQP9N6eLSHhNUy49T1JVtY',
total_supply: null, total_supply: null,
type: 'ERC-721', type: 'ERC-721',
icon_url: null,
}; };
export const tokenInfoERC1155a: TokenInfo = { export const tokenInfoERC1155a: TokenInfo = {
...@@ -124,6 +134,7 @@ export const tokenInfoERC1155a: TokenInfo = { ...@@ -124,6 +134,7 @@ export const tokenInfoERC1155a: TokenInfo = {
symbol: 'HYFI_MEMBERSHIP', symbol: 'HYFI_MEMBERSHIP',
total_supply: '482', total_supply: '482',
type: 'ERC-1155', type: 'ERC-1155',
icon_url: null,
}; };
export const tokenInfoERC1155b: TokenInfo = { export const tokenInfoERC1155b: TokenInfo = {
...@@ -135,6 +146,7 @@ export const tokenInfoERC1155b: TokenInfo = { ...@@ -135,6 +146,7 @@ export const tokenInfoERC1155b: TokenInfo = {
symbol: 'WVC', symbol: 'WVC',
total_supply: '4943', total_supply: '4943',
type: 'ERC-1155', type: 'ERC-1155',
icon_url: null,
}; };
export const tokenInfoERC1155WithoutName: TokenInfo = { export const tokenInfoERC1155WithoutName: TokenInfo = {
...@@ -146,4 +158,5 @@ export const tokenInfoERC1155WithoutName: TokenInfo = { ...@@ -146,4 +158,5 @@ export const tokenInfoERC1155WithoutName: TokenInfo = {
symbol: null, symbol: null,
total_supply: '482', total_supply: '482',
type: 'ERC-1155', type: 'ERC-1155',
icon_url: null,
}; };
...@@ -30,6 +30,7 @@ export const erc20: TokenTransfer = { ...@@ -30,6 +30,7 @@ export const erc20: TokenTransfer = {
symbol: 'ARIA', symbol: 'ARIA',
type: 'ERC-20', type: 'ERC-20',
total_supply: '0', total_supply: '0',
icon_url: null,
}, },
total: { total: {
decimals: '18', decimals: '18',
...@@ -73,6 +74,7 @@ export const erc721: TokenTransfer = { ...@@ -73,6 +74,7 @@ export const erc721: TokenTransfer = {
symbol: 'AriaSA', symbol: 'AriaSA',
type: 'ERC-721', type: 'ERC-721',
total_supply: '0', total_supply: '0',
icon_url: null,
}, },
total: { total: {
token_id: '875879856', token_id: '875879856',
...@@ -115,6 +117,7 @@ export const erc1155A: TokenTransfer = { ...@@ -115,6 +117,7 @@ export const erc1155A: TokenTransfer = {
symbol: 'MY_SYMBOL_IS_VERY_LONG', symbol: 'MY_SYMBOL_IS_VERY_LONG',
type: 'ERC-1155', type: 'ERC-1155',
total_supply: '0', total_supply: '0',
icon_url: null,
}, },
total: { total: {
token_id: '123', token_id: '123',
......
...@@ -31,6 +31,7 @@ export const mintToken: TxStateChange = { ...@@ -31,6 +31,7 @@ export const mintToken: TxStateChange = {
symbol: 'nMOONBIRD', symbol: 'nMOONBIRD',
total_supply: '10645', total_supply: '10645',
type: 'ERC-721', type: 'ERC-721',
icon_url: null,
}, },
type: 'token', type: 'token',
}; };
...@@ -66,6 +67,7 @@ export const receiveMintedToken: TxStateChange = { ...@@ -66,6 +67,7 @@ export const receiveMintedToken: TxStateChange = {
symbol: 'nMOONBIRD', symbol: 'nMOONBIRD',
total_supply: '10645', total_supply: '10645',
type: 'ERC-721', type: 'ERC-721',
icon_url: null,
}, },
type: 'token', type: 'token',
}; };
......
...@@ -9,7 +9,7 @@ import type { ResourceError } from 'lib/api/resources'; ...@@ -9,7 +9,7 @@ import type { ResourceError } from 'lib/api/resources';
import { AppContextProvider } from 'lib/appContext'; import { AppContextProvider } from 'lib/appContext';
import { Chakra } from 'lib/Chakra'; import { Chakra } from 'lib/Chakra';
import { ScrollDirectionProvider } from 'lib/contexts/scrollDirection'; import { ScrollDirectionProvider } from 'lib/contexts/scrollDirection';
import getErrorStatusCode from 'lib/errors/getErrorStatusCode'; import getErrorCauseStatusCode from 'lib/errors/getErrorCauseStatusCode';
import useConfigSentry from 'lib/hooks/useConfigSentry'; import useConfigSentry from 'lib/hooks/useConfigSentry';
import { SocketProvider } from 'lib/socket/context'; import { SocketProvider } from 'lib/socket/context';
import theme from 'theme'; import theme from 'theme';
...@@ -29,7 +29,7 @@ function MyApp({ Component, pageProps }: AppProps) { ...@@ -29,7 +29,7 @@ function MyApp({ Component, pageProps }: AppProps) {
refetchOnWindowFocus: false, refetchOnWindowFocus: false,
retry: (failureCount, _error) => { retry: (failureCount, _error) => {
const error = _error as ResourceError<{ status: number }>; const error = _error as ResourceError<{ status: number }>;
const status = error?.status || error?.payload?.status; const status = error?.payload?.status || error?.status;
if (status && status >= 400 && status < 500) { if (status && status >= 400 && status < 500) {
// don't do retry for client error responses // don't do retry for client error responses
return false; return false;
...@@ -42,7 +42,7 @@ function MyApp({ Component, pageProps }: AppProps) { ...@@ -42,7 +42,7 @@ function MyApp({ Component, pageProps }: AppProps) {
})); }));
const renderErrorScreen = React.useCallback((error?: Error) => { const renderErrorScreen = React.useCallback((error?: Error) => {
const statusCode = getErrorStatusCode(error); const statusCode = getErrorCauseStatusCode(error);
return ( return (
<AppError <AppError
......
...@@ -4,17 +4,20 @@ import React from 'react'; ...@@ -4,17 +4,20 @@ import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle'; import getNetworkTitle from 'lib/networks/getNetworkTitle';
import ApiKeys from 'ui/pages/ApiKeys'; import ApiKeys from 'ui/pages/ApiKeys';
import Page from 'ui/shared/Page/Page';
const ApiKeysPage: NextPage = () => { const ApiKeysPage: NextPage = () => {
const title = getNetworkTitle(); const title = getNetworkTitle();
return ( return (
<> <>
<Head><title>{ title }</title></Head> <Head><title>{ title }</title></Head>
<Page>
<ApiKeys/> <ApiKeys/>
</Page>
</> </>
); );
}; };
export default ApiKeysPage; export default ApiKeysPage;
export { getServerSideProps } from 'lib/next/getServerSideProps'; export { getServerSideProps } from 'lib/next/account/getServerSideProps';
...@@ -4,17 +4,20 @@ import React from 'react'; ...@@ -4,17 +4,20 @@ import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle'; import getNetworkTitle from 'lib/networks/getNetworkTitle';
import CustomAbi from 'ui/pages/CustomAbi'; import CustomAbi from 'ui/pages/CustomAbi';
import Page from 'ui/shared/Page/Page';
const CustomAbiPage: NextPage = () => { const CustomAbiPage: NextPage = () => {
const title = getNetworkTitle(); const title = getNetworkTitle();
return ( return (
<> <>
<Head><title>{ title }</title></Head> <Head><title>{ title }</title></Head>
<Page>
<CustomAbi/> <CustomAbi/>
</Page>
</> </>
); );
}; };
export default CustomAbiPage; export default CustomAbiPage;
export { getServerSideProps } from 'lib/next/getServerSideProps'; export { getServerSideProps } from 'lib/next/account/getServerSideProps';
...@@ -4,17 +4,20 @@ import React from 'react'; ...@@ -4,17 +4,20 @@ import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle'; import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PublicTags from 'ui/pages/PublicTags'; import PublicTags from 'ui/pages/PublicTags';
import Page from 'ui/shared/Page/Page';
const PublicTagsPage: NextPage = () => { const PublicTagsPage: NextPage = () => {
const title = getNetworkTitle(); const title = getNetworkTitle();
return ( return (
<> <>
<Head><title>{ title }</title></Head> <Head><title>{ title }</title></Head>
<Page>
<PublicTags/> <PublicTags/>
</Page>
</> </>
); );
}; };
export default PublicTagsPage; export default PublicTagsPage;
export { getServerSideProps } from 'lib/next/getServerSideProps'; export { getServerSideProps } from 'lib/next/account/getServerSideProps';
...@@ -4,17 +4,20 @@ import React from 'react'; ...@@ -4,17 +4,20 @@ import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle'; import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PrivateTags from 'ui/pages/PrivateTags'; import PrivateTags from 'ui/pages/PrivateTags';
import Page from 'ui/shared/Page/Page';
const AddressTagsPage: NextPage = () => { const AddressTagsPage: NextPage = () => {
const title = getNetworkTitle(); const title = getNetworkTitle();
return ( return (
<> <>
<Head><title>{ title }</title></Head> <Head><title>{ title }</title></Head>
<Page>
<PrivateTags/> <PrivateTags/>
</Page>
</> </>
); );
}; };
export default AddressTagsPage; export default AddressTagsPage;
export { getServerSideProps } from 'lib/next/getServerSideProps'; export { getServerSideProps } from 'lib/next/account/getServerSideProps';
import type { NextPage } from 'next';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import VerifiedAddresses from 'ui/pages/VerifiedAddresses';
import Page from 'ui/shared/Page/Page';
const VerifiedAddressesPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head><title>{ title }</title></Head>
<Page>
<VerifiedAddresses/>
</Page>
</>
);
};
export default VerifiedAddressesPage;
export { getServerSidePropsForVerifiedAddresses as getServerSideProps } from 'lib/next/account/getServerSideProps';
...@@ -4,6 +4,7 @@ import React from 'react'; ...@@ -4,6 +4,7 @@ import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle'; import getNetworkTitle from 'lib/networks/getNetworkTitle';
import WatchList from 'ui/pages/Watchlist'; import WatchList from 'ui/pages/Watchlist';
import Page from 'ui/shared/Page/Page';
const WatchListPage: NextPage = () => { const WatchListPage: NextPage = () => {
const title = getNetworkTitle(); const title = getNetworkTitle();
...@@ -12,11 +13,13 @@ const WatchListPage: NextPage = () => { ...@@ -12,11 +13,13 @@ const WatchListPage: NextPage = () => {
<Head> <Head>
<title>{ title }</title> <title>{ title }</title>
</Head> </Head>
<Page>
<WatchList/> <WatchList/>
</Page>
</> </>
); );
}; };
export default WatchListPage; export default WatchListPage;
export { getServerSideProps } from 'lib/next/getServerSideProps'; export { getServerSideProps } from 'lib/next/account/getServerSideProps';
...@@ -15,7 +15,7 @@ const APIDocsPage: NextPage = () => { ...@@ -15,7 +15,7 @@ const APIDocsPage: NextPage = () => {
return ( return (
<Page> <Page>
<PageTitle text="API Documentation"/> <PageTitle title="API Documentation"/>
<Head><title>{ `API for the ${ networkTitle }` }</title></Head> <Head><title>{ `API for the ${ networkTitle }` }</title></Head>
<SwaggerUI/> <SwaggerUI/>
</Page> </Page>
......
...@@ -9,7 +9,7 @@ import PageTitle from 'ui/shared/Page/PageTitle'; ...@@ -9,7 +9,7 @@ import PageTitle from 'ui/shared/Page/PageTitle';
const MarketplacePage: NextPage = () => { const MarketplacePage: NextPage = () => {
return ( return (
<Page> <Page>
<PageTitle text="Marketplace"/> <PageTitle title="Marketplace"/>
<Head><title>Blockscout | Marketplace</title></Head> <Head><title>Blockscout | Marketplace</title></Head>
<Marketplace/> <Marketplace/>
......
...@@ -3,16 +3,19 @@ import Head from 'next/head'; ...@@ -3,16 +3,19 @@ import Head from 'next/head';
import React from 'react'; import React from 'react';
import MyProfile from 'ui/pages/MyProfile'; import MyProfile from 'ui/pages/MyProfile';
import Page from 'ui/shared/Page/Page';
const MyProfilePage: NextPage = () => { const MyProfilePage: NextPage = () => {
return ( return (
<> <>
<Head><title>My profile</title></Head> <Head><title>My profile</title></Head>
<Page>
<MyProfile/> <MyProfile/>
</Page>
</> </>
); );
}; };
export default MyProfilePage; export default MyProfilePage;
export { getServerSideProps } from 'lib/next/getServerSideProps'; export { getServerSideProps } from 'lib/next/account/getServerSideProps';
import type { NextPage } from 'next';
import Head from 'next/head';
import React from 'react';
import Graph from 'ui/pages/Graph';
const GraphPage: NextPage = () => {
return (
<>
<Head><title>Graph Page</title></Head>
<Graph/>
</>
);
};
export default GraphPage;
export { getServerSideProps } from 'lib/next/getServerSideProps';
...@@ -16,7 +16,7 @@ const GraphiqlPage: NextPage = () => { ...@@ -16,7 +16,7 @@ const GraphiqlPage: NextPage = () => {
return ( return (
<Page> <Page>
<Head><title>Graph Page</title></Head> <Head><title>Graph Page</title></Head>
<PageTitle text="GraphQL playground"/> <PageTitle title="GraphQL playground"/>
<GraphQL/> <GraphQL/>
</Page> </Page>
); );
......
...@@ -7,7 +7,7 @@ interface Env { ...@@ -7,7 +7,7 @@ interface Env {
} }
// keep in mind that all passed variables here should be present in env config files (.env.pw or .env.poa) // keep in mind that all passed variables here should be present in env config files (.env.pw or .env.poa)
export default function contextWithEnvs(envs: Array<Env>): Parameters<typeof test.extend>[0]['context'] { export default function contextWithEnvsFixture(envs: Array<Env>): Parameters<typeof test.extend>[0]['context'] {
return async({ browser }, use) => { return async({ browser }, use) => {
const context = await createContextWithEnvs(browser, envs); const context = await createContextWithEnvs(browser, envs);
......
...@@ -14,6 +14,7 @@ export const TOKEN_INFO_ERC_20: TokenInfo<'ERC-20'> = { ...@@ -14,6 +14,7 @@ export const TOKEN_INFO_ERC_20: TokenInfo<'ERC-20'> = {
symbol: 'STUB', symbol: 'STUB',
total_supply: '6000000000000000000', total_supply: '6000000000000000000',
type: 'ERC-20', type: 'ERC-20',
icon_url: null,
}; };
export const TOKEN_INFO_ERC_721: TokenInfo<'ERC-721'> = { export const TOKEN_INFO_ERC_721: TokenInfo<'ERC-721'> = {
......
...@@ -50,6 +50,16 @@ const colors = { ...@@ -50,6 +50,16 @@ const colors = {
'800': 'RGBA(16, 17, 18, 0.80)', '800': 'RGBA(16, 17, 18, 0.80)',
'900': 'RGBA(16, 17, 18, 0.92)', '900': 'RGBA(16, 17, 18, 0.92)',
}, },
github: '#171923',
telegram: '#2775CA',
linkedin: '#1564BA',
discord: '#9747FF',
slack: '#1BA27A',
twitter: '#63B3ED',
opensea: '#2081E2',
facebook: '#4460A0',
medium: '#231F20',
reddit: '#FF4500',
}; };
export default colors; export default colors;
import { theme } from '@chakra-ui/react'; import { theme } from '@chakra-ui/react';
export const BODY_TYPEFACE = 'Inter'; export const BODY_TYPEFACE = 'Inter';
export const HEADING_TYPEFACE = 'Poppins';
const typography = { const typography = {
fonts: { fonts: {
heading: `Poppins, ${ theme.fonts.heading }`, heading: `${ HEADING_TYPEFACE }, ${ theme.fonts.heading }`,
body: `${ BODY_TYPEFACE }, ${ theme.fonts.body }`, body: `${ BODY_TYPEFACE }, ${ theme.fonts.body }`,
}, },
textStyles: { textStyles: {
......
...@@ -3,7 +3,6 @@ const zIndices = { ...@@ -3,7 +3,6 @@ const zIndices = {
auto: 'auto', auto: 'auto',
base: 0, base: 0,
docked: 10, docked: 10,
tooltip: 900,
dropdown: 1000, dropdown: 1000,
sticky: 1100, sticky: 1100,
sticky1: 1101, sticky1: 1101,
...@@ -12,6 +11,7 @@ const zIndices = { ...@@ -12,6 +11,7 @@ const zIndices = {
overlay: 1300, overlay: 1300,
modal: 1400, modal: 1400,
popover: 1500, popover: 1500,
tooltip: 1550, // otherwise tooltips will not be visible in modals
skipLink: 1600, skipLink: 1600,
toast: 1700, toast: 1700,
}; };
......
...@@ -160,3 +160,58 @@ export type PublicTagErrors = { ...@@ -160,3 +160,58 @@ export type PublicTagErrors = {
full_name: Array<string>; full_name: Array<string>;
tags: Array<string>; tags: Array<string>;
} }
export interface VerifiedAddress {
userId: string;
chainId: string;
contractAddress: string;
verifiedDate: string;
metadata: {
tokenName: string | null;
tokenSymbol: string | null;
};
}
export interface VerifiedAddressResponse {
verifiedAddresses: Array<VerifiedAddress>;
}
export interface TokenInfoApplicationConfig {
projectSectors: Array<string>;
}
export interface TokenInfoApplication {
adminComments?: string;
coinGeckoTicker?: string;
coinMarketCapTicker?: string;
comment?: string;
defiLlamaTicker?: string;
discord?: string;
docs?: string;
facebook?: string;
github?: string;
iconUrl: string;
id: string;
linkedin?: string;
medium?: string;
openSea?: string;
projectDescription?: string;
projectEmail: string;
projectName?: string;
projectSector?: string;
projectWebsite: string;
reddit?: string;
requesterEmail: string;
requesterName: string;
slack?: string;
status: 'STATUS_UNKNOWN' | 'IN_PROCESS' | 'APPROVED' | 'REJECTED' | 'UPDATE_REQUIRED';
support?: string;
telegram?: string;
tokenAddress: string;
twitter?: string;
updatedAt: string;
}
export interface TokenInfoApplications {
submissions: Array<TokenInfoApplication>;
}
import type { Transaction } from 'types/api/transaction'; import type { Transaction } from 'types/api/transaction';
import type { AddressTag, WatchlistName } from './addressParams'; import type { UserTags } from './addressParams';
import type { Block } from './block'; import type { Block } from './block';
import type { InternalTransaction } from './internalTransaction'; import type { InternalTransaction } from './internalTransaction';
import type { TokenInfo, TokenType } from './token'; import type { TokenInfo, TokenInstance, TokenType } from './token';
import type { TokenTransfer, TokenTransferPagination } from './tokenTransfer'; import type { TokenTransfer, TokenTransferPagination } from './tokenTransfer';
export interface Address { export interface Address extends UserTags {
block_number_balance_updated_at: number | null; block_number_balance_updated_at: number | null;
coin_balance: string | null; coin_balance: string | null;
creator_address_hash: string | null; creator_address_hash: string | null;
...@@ -30,11 +30,8 @@ export interface Address { ...@@ -30,11 +30,8 @@ export interface Address {
is_contract: boolean; is_contract: boolean;
is_verified: boolean; is_verified: boolean;
name: string | null; name: string | null;
private_tags: Array<AddressTag> | null;
public_tags: Array<AddressTag> | null;
token: TokenInfo | null; token: TokenInfo | null;
watchlist_address_id: number | null; watchlist_address_id: number | null;
watchlist_names: Array<WatchlistName> | null;
} }
export interface AddressCounters { export interface AddressCounters {
...@@ -48,6 +45,7 @@ export interface AddressTokenBalance { ...@@ -48,6 +45,7 @@ export interface AddressTokenBalance {
token: TokenInfo; token: TokenInfo;
token_id: string | null; token_id: string | null;
value: string; value: string;
token_instance?: TokenInstance;
} }
export interface AddressTokensResponse { export interface AddressTokensResponse {
......
...@@ -9,13 +9,16 @@ export interface WatchlistName { ...@@ -9,13 +9,16 @@ export interface WatchlistName {
display_name: string; display_name: string;
} }
export interface AddressParam { export interface UserTags {
private_tags: Array<AddressTag> | null;
watchlist_names: Array<WatchlistName> | null;
public_tags: Array<AddressTag> | null;
}
export interface AddressParam extends UserTags {
hash: string; hash: string;
implementation_name: string | null; implementation_name: string | null;
name: string | null; name: string | null;
is_contract: boolean; is_contract: boolean;
is_verified: boolean | null; is_verified: boolean | null;
private_tags: Array<AddressTag> | null;
watchlist_names: Array<WatchlistName> | null;
public_tags: Array<AddressTag> | null;
} }
...@@ -13,20 +13,20 @@ export interface SearchResultAddressOrContract { ...@@ -13,20 +13,20 @@ export interface SearchResultAddressOrContract {
type: 'address' | 'contract'; type: 'address' | 'contract';
name: string | null; name: string | null;
address: string; address: string;
url: string; url?: string; // not used by the frontend, we build the url ourselves
} }
export interface SearchResultBlock { export interface SearchResultBlock {
type: 'block'; type: 'block';
block_number: number; block_number: number | string;
block_hash: string; block_hash: string;
url: string; url?: string; // not used by the frontend, we build the url ourselves
} }
export interface SearchResultTx { export interface SearchResultTx {
type: 'transaction'; type: 'transaction';
tx_hash: string; tx_hash: string;
url: string; url?: string; // not used by the frontend, we build the url ourselves
} }
export type SearchResultItem = SearchResultToken | SearchResultAddressOrContract | SearchResultBlock | SearchResultTx; export type SearchResultItem = SearchResultToken | SearchResultAddressOrContract | SearchResultBlock | SearchResultTx;
......
import type { TokenInfoApplication } from './account';
import type { AddressParam } from './addressParams'; import type { AddressParam } from './addressParams';
export type TokenType = 'ERC-20' | 'ERC-721' | 'ERC-1155'; export type TokenType = 'ERC-20' | 'ERC-721' | 'ERC-1155';
...@@ -11,6 +12,7 @@ export interface TokenInfo<T extends TokenType = TokenType> { ...@@ -11,6 +12,7 @@ export interface TokenInfo<T extends TokenType = TokenType> {
holders: string | null; holders: string | null;
exchange_rate: string | null; exchange_rate: string | null;
total_supply: string | null; total_supply: string | null;
icon_url: string | null;
} }
export interface TokenCounters { export interface TokenCounters {
...@@ -57,3 +59,5 @@ export interface TokenInventoryResponse { ...@@ -57,3 +59,5 @@ export interface TokenInventoryResponse {
export type TokenInventoryPagination = { export type TokenInventoryPagination = {
unique_token: number; unique_token: number;
} }
export type TokenVerifiedInfo = Omit<TokenInfoApplication, 'id' | 'status'>;
import type { Route } from 'nextjs-routes';
type NavItemCommon = {
text: string;
icon?: React.FunctionComponent<React.SVGAttributes<SVGElement>>;
}
export type NavItemInternal = NavItemCommon & {
nextRoute: Route;
isActive?: boolean;
}
export type NavItemExternal = NavItemCommon & {
url: string;
}
export type NavItem = NavItemInternal | NavItemExternal
export type NavGroupItem = NavItemCommon & {
isActive?: boolean;
subItems: Array<NavItem> | Array<Array<NavItem>>;
}
...@@ -15,6 +15,8 @@ export interface NetworkExplorer { ...@@ -15,6 +15,8 @@ export interface NetworkExplorer {
paths: { paths: {
tx?: string; tx?: string;
address?: string; address?: string;
token?: string;
block?: string;
}; };
} }
......
...@@ -10,6 +10,7 @@ declare module "nextjs-routes" { ...@@ -10,6 +10,7 @@ declare module "nextjs-routes" {
| StaticRoute<"/account/custom_abi"> | StaticRoute<"/account/custom_abi">
| StaticRoute<"/account/public_tags_request"> | StaticRoute<"/account/public_tags_request">
| StaticRoute<"/account/tag_address"> | StaticRoute<"/account/tag_address">
| StaticRoute<"/account/verified_addresses">
| StaticRoute<"/account/watchlist"> | StaticRoute<"/account/watchlist">
| StaticRoute<"/accounts"> | StaticRoute<"/accounts">
| DynamicRoute<"/address/[hash]/contract_verification", { "hash": string }> | DynamicRoute<"/address/[hash]/contract_verification", { "hash": string }>
...@@ -25,7 +26,6 @@ declare module "nextjs-routes" { ...@@ -25,7 +26,6 @@ declare module "nextjs-routes" {
| DynamicRoute<"/block/[height]", { "height": string }> | DynamicRoute<"/block/[height]", { "height": string }>
| StaticRoute<"/blocks"> | StaticRoute<"/blocks">
| StaticRoute<"/csv-export"> | StaticRoute<"/csv-export">
| StaticRoute<"/graph">
| StaticRoute<"/graphiql"> | StaticRoute<"/graphiql">
| StaticRoute<"/"> | StaticRoute<"/">
| StaticRoute<"/l2-deposits"> | StaticRoute<"/l2-deposits">
......
import { useColorModeValue, useToken } from '@chakra-ui/react';
import {
EthereumClient,
modalConnectors,
walletConnectProvider,
} from '@web3modal/ethereum';
import { Web3Modal } from '@web3modal/react';
import React from 'react'; import React from 'react';
import type { Chain } from 'wagmi';
import { configureChains, createClient, WagmiConfig } from 'wagmi';
import type { RoutedSubTab } from 'ui/shared/Tabs/types'; import type { RoutedSubTab } from 'ui/shared/Tabs/types';
import appConfig from 'configs/app/config';
import { ContractContextProvider } from 'ui/address/contract/context'; import { ContractContextProvider } from 'ui/address/contract/context';
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs'; import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
import Web3ModalProvider from 'ui/shared/Web3ModalProvider';
interface Props { interface Props {
tabs: Array<RoutedSubTab>; tabs: Array<RoutedSubTab>;
addressHash?: string; addressHash?: string;
} }
const { wagmiClient, ethereumClient } = (() => {
try {
const currentChain: Chain = {
id: Number(appConfig.network.id),
name: appConfig.network.name || '',
network: appConfig.network.name || '',
nativeCurrency: {
decimals: appConfig.network.currency.decimals,
name: appConfig.network.currency.name || '',
symbol: appConfig.network.currency.symbol || '',
},
rpcUrls: {
'default': {
http: [ appConfig.network.rpcUrl || '' ],
},
},
blockExplorers: {
'default': {
name: 'Blockscout',
url: appConfig.baseUrl,
},
},
};
const chains = [ currentChain ];
const { provider } = configureChains(chains, [
walletConnectProvider({ projectId: appConfig.walletConnect.projectId || '' }),
]);
const wagmiClient = createClient({
autoConnect: true,
connectors: modalConnectors({ appName: 'web3Modal', chains }),
provider,
});
const ethereumClient = new EthereumClient(wagmiClient, chains);
return { wagmiClient, ethereumClient };
} catch (error) {
return { wagmiClient: undefined, ethereumClient: undefined };
}
})();
const TAB_LIST_PROPS = { const TAB_LIST_PROPS = {
columnGap: 3, columnGap: 3,
}; };
const AddressContract = ({ addressHash, tabs }: Props) => { const AddressContract = ({ addressHash, tabs }: Props) => {
const modalZIndex = useToken<string>('zIndices', 'modal'); const fallback = React.useCallback(() => {
const web3ModalTheme = useColorModeValue('light', 'dark'); const noProviderTabs = tabs.filter(({ id }) => id === 'contact_code');
const noProviderTabs = React.useMemo(() => tabs.filter(({ id }) => id === 'contact_code'), [ tabs ]);
if (!wagmiClient || !ethereumClient) {
return <RoutedTabs tabs={ noProviderTabs } variant="outline" colorScheme="gray" size="sm" tabListProps={ TAB_LIST_PROPS }/>; return <RoutedTabs tabs={ noProviderTabs } variant="outline" colorScheme="gray" size="sm" tabListProps={ TAB_LIST_PROPS }/>;
} }, [ tabs ]);
return ( return (
<WagmiConfig client={ wagmiClient }> <Web3ModalProvider fallback={ fallback }>
<ContractContextProvider addressHash={ addressHash }> <ContractContextProvider addressHash={ addressHash }>
<RoutedTabs tabs={ tabs } variant="outline" colorScheme="gray" size="sm" tabListProps={ TAB_LIST_PROPS }/> <RoutedTabs tabs={ tabs } variant="outline" colorScheme="gray" size="sm" tabListProps={ TAB_LIST_PROPS }/>
</ContractContextProvider> </ContractContextProvider>
<Web3Modal </Web3ModalProvider>
projectId={ appConfig.walletConnect.projectId }
ethereumClient={ ethereumClient }
themeZIndex={ Number(modalZIndex) }
themeMode={ web3ModalTheme }
themeBackground="themeColor"
/>
</WagmiConfig>
); );
}; };
......
import { Box, Flex, Text, Icon, Grid } from '@chakra-ui/react'; import { Box, Text, Icon, Grid } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query'; import type { UseQueryResult } from '@tanstack/react-query';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
...@@ -6,7 +6,6 @@ import React from 'react'; ...@@ -6,7 +6,6 @@ import React from 'react';
import type { Address as TAddress } from 'types/api/address'; import type { Address as TAddress } from 'types/api/address';
import appConfig from 'configs/app/config';
import blockIcon from 'icons/block.svg'; import blockIcon from 'icons/block.svg';
import type { ResourceError } from 'lib/api/resources'; import type { ResourceError } from 'lib/api/resources';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
...@@ -18,7 +17,6 @@ import DataFetchAlert from 'ui/shared/DataFetchAlert'; ...@@ -18,7 +17,6 @@ import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem'; import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import DetailsSponsoredItem from 'ui/shared/DetailsSponsoredItem'; import DetailsSponsoredItem from 'ui/shared/DetailsSponsoredItem';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic'; import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal'; import LinkInternal from 'ui/shared/LinkInternal';
import AddressBalance from './details/AddressBalance'; import AddressBalance from './details/AddressBalance';
...@@ -83,21 +81,11 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => { ...@@ -83,21 +81,11 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
return <AddressDetailsSkeleton/>; return <AddressDetailsSkeleton/>;
} }
const explorers = appConfig.network.explorers.filter(({ paths }) => paths.address);
const data = addressQuery.isError ? errorData : addressQuery.data; const data = addressQuery.isError ? errorData : addressQuery.data;
return ( return (
<Box> <Box>
<AddressHeadingInfo address={ data } token={ data.token } isLinkDisabled/> <AddressHeadingInfo address={ data } token={ data.token } isLinkDisabled/>
{ explorers.length > 0 && (
<Flex mt={ 8 } columnGap={ 4 } flexWrap="wrap">
<Text fontSize="sm">Verify with other explorers</Text>
{ explorers.map((explorer) => {
const url = new URL(explorer.paths.address + '/' + addressHash, explorer.baseUrl);
return <LinkExternal key={ explorer.baseUrl } href={ url.toString() }>{ explorer.title }</LinkExternal>;
}) }
</Flex>
) }
<Grid <Grid
mt={ 8 } mt={ 8 }
columnGap={ 8 } columnGap={ 8 }
......
...@@ -194,11 +194,17 @@ const AddressTokenTransfers = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLD ...@@ -194,11 +194,17 @@ const AddressTokenTransfers = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLD
</> </>
) : null; ) : null;
const tokenData = React.useMemo(() => ({
address: tokenFilter || '',
name: '',
icon_url: '',
}), [ tokenFilter ]);
const tokenFilterComponent = tokenFilter && ( const tokenFilterComponent = tokenFilter && (
<Flex alignItems="center" flexWrap="wrap" mb={{ base: isActionBarHidden ? 3 : 6, lg: 0 }} mr={ 4 }> <Flex alignItems="center" flexWrap="wrap" mb={{ base: isActionBarHidden ? 3 : 6, lg: 0 }} mr={ 4 }>
<Text whiteSpace="nowrap" mr={ 2 } py={ 1 }>Filtered by token</Text> <Text whiteSpace="nowrap" mr={ 2 } py={ 1 }>Filtered by token</Text>
<Flex alignItems="center" py={ 1 }> <Flex alignItems="center" py={ 1 }>
<TokenLogo hash={ tokenFilter } boxSize={ 6 } mr={ 2 }/> <TokenLogo data={ tokenData } boxSize={ 6 } mr={ 2 }/>
{ isMobile ? <HashStringShorten hash={ tokenFilter }/> : tokenFilter } { isMobile ? <HashStringShorten hash={ tokenFilter }/> : tokenFilter }
<Tooltip label="Reset filter"> <Tooltip label="Reset filter">
<Flex> <Flex>
......
...@@ -222,7 +222,7 @@ const ContractCode = ({ addressHash, noSocket }: Props) => { ...@@ -222,7 +222,7 @@ const ContractCode = ({ addressHash, noSocket }: Props) => {
<RawDataSnippet <RawDataSnippet
data={ data.creation_bytecode } data={ data.creation_bytecode }
title="Contract creation code" title="Contract creation code"
rightSlot={ data.is_verified ? null : verificationButton } rightSlot={ data.is_verified || data.is_self_destructed ? null : verificationButton }
beforeSlot={ data.is_self_destructed ? ( beforeSlot={ data.is_self_destructed ? (
<Alert status="info" whiteSpace="pre-wrap" mb={ 3 }> <Alert status="info" whiteSpace="pre-wrap" mb={ 3 }>
Contracts that self destruct in their constructors have no contract code published and cannot be verified. Contracts that self destruct in their constructors have no contract code published and cannot be verified.
......
...@@ -63,6 +63,12 @@ const AddressBalance = ({ data }: Props) => { ...@@ -63,6 +63,12 @@ const AddressBalance = ({ data }: Props) => {
handler: handleNewCoinBalanceMessage, handler: handleNewCoinBalanceMessage,
}); });
const tokenData = React.useMemo(() => ({
address: appConfig.network.currency.address || '',
name: appConfig.network.currency.name || '',
icon_url: '',
}), [ ]);
return ( return (
<DetailsInfoItem <DetailsInfoItem
title="Balance" title="Balance"
...@@ -71,8 +77,7 @@ const AddressBalance = ({ data }: Props) => { ...@@ -71,8 +77,7 @@ const AddressBalance = ({ data }: Props) => {
alignItems="flex-start" alignItems="flex-start"
> >
<TokenLogo <TokenLogo
hash={ appConfig.network.currency.address } data={ tokenData }
name={ appConfig.network.currency.name }
boxSize={ 5 } boxSize={ 5 }
mr={ 2 } mr={ 2 }
fontSize="sm" fontSize="sm"
......
...@@ -3,14 +3,14 @@ import { useQueryClient } from '@tanstack/react-query'; ...@@ -3,14 +3,14 @@ import { useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { UserInfo } from 'types/api/account';
import starFilledIcon from 'icons/star_filled.svg'; import starFilledIcon from 'icons/star_filled.svg';
import starOutlineIcon from 'icons/star_outline.svg'; import starOutlineIcon from 'icons/star_outline.svg';
import type { ResourceError } from 'lib/api/resources';
import { resourceKey } from 'lib/api/resources'; import { resourceKey } from 'lib/api/resources';
import { getResourceKey } from 'lib/api/useApiQuery'; import { getResourceKey } from 'lib/api/useApiQuery';
import useLoginUrl from 'lib/hooks/useLoginUrl';
import usePreventFocusAfterModalClosing from 'lib/hooks/usePreventFocusAfterModalClosing'; import usePreventFocusAfterModalClosing from 'lib/hooks/usePreventFocusAfterModalClosing';
import useRedirectIfNotAuth from 'lib/hooks/useRedirectIfNotAuth';
import useToast from 'lib/hooks/useToast';
import WatchlistAddModal from 'ui/watchlist/AddressModal/AddressModal'; import WatchlistAddModal from 'ui/watchlist/AddressModal/AddressModal';
import DeleteAddressModal from 'ui/watchlist/DeleteAddressModal'; import DeleteAddressModal from 'ui/watchlist/DeleteAddressModal';
...@@ -25,18 +25,33 @@ const AddressFavoriteButton = ({ className, hash, watchListId }: Props) => { ...@@ -25,18 +25,33 @@ const AddressFavoriteButton = ({ className, hash, watchListId }: Props) => {
const deleteModalProps = useDisclosure(); const deleteModalProps = useDisclosure();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const router = useRouter(); const router = useRouter();
const toast = useToast();
const redirectIfNotAuth = useRedirectIfNotAuth();
const profileData = queryClient.getQueryData<UserInfo>([ resourceKey('user_info') ]); const profileState = queryClient.getQueryState<unknown, ResourceError<{ message: string }>>([ resourceKey('user_info') ]);
const isAuth = Boolean(profileData);
const loginUrl = useLoginUrl();
const handleClick = React.useCallback(() => { const handleClick = React.useCallback(() => {
if (!isAuth) { if (profileState?.error?.status === 403) {
window.location.assign(loginUrl); const isUnverifiedEmail = profileState.error.payload?.message.includes('Unverified email');
if (isUnverifiedEmail) {
toast({
position: 'top-right',
title: 'Error',
description: 'Unable to add address to watch list. Please go to the watch list page instead.',
status: 'error',
variant: 'subtle',
isClosable: true,
});
return;
}
}
if (redirectIfNotAuth()) {
return; return;
} }
watchListId ? deleteModalProps.onOpen() : addModalProps.onOpen(); watchListId ? deleteModalProps.onOpen() : addModalProps.onOpen();
}, [ addModalProps, deleteModalProps, watchListId, isAuth, loginUrl ]); }, [ profileState, redirectIfNotAuth, watchListId, deleteModalProps, addModalProps, toast ]);
const handleAddOrDeleteSuccess = React.useCallback(async() => { const handleAddOrDeleteSuccess = React.useCallback(async() => {
const queryKey = getResourceKey('address', { pathParams: { hash: router.query.hash?.toString() } }); const queryKey = getResourceKey('address', { pathParams: { hash: router.query.hash?.toString() } });
......
...@@ -65,7 +65,7 @@ const TokenSelectItem = ({ data }: Props) => { ...@@ -65,7 +65,7 @@ const TokenSelectItem = ({ data }: Props) => {
href={ url } href={ url }
> >
<Flex alignItems="center" w="100%"> <Flex alignItems="center" w="100%">
<TokenLogo hash={ data.token.address } name={ data.token.name } boxSize={ 6 }/> <TokenLogo data={ data.token } boxSize={ 6 }/>
<Text fontWeight={ 700 } ml={ 2 }>{ data.token.name || <HashStringShorten hash={ data.token.address }/> }</Text> <Text fontWeight={ 700 } ml={ 2 }>{ data.token.name || <HashStringShorten hash={ data.token.address }/> }</Text>
{ data.usd && <Text fontWeight={ 700 } ml="auto">${ data.usd.toFormat(2) }</Text> } { data.usd && <Text fontWeight={ 700 } ml="auto">${ data.usd.toFormat(2) }</Text> }
</Flex> </Flex>
......
...@@ -24,7 +24,7 @@ const ERC20TokensListItem = ({ token, value }: Props) => { ...@@ -24,7 +24,7 @@ const ERC20TokensListItem = ({ token, value }: Props) => {
return ( return (
<ListItemMobile rowGap={ 2 }> <ListItemMobile rowGap={ 2 }>
<Flex alignItems="center" width="100%"> <Flex alignItems="center" width="100%">
<TokenLogo hash={ token.address } name={ token.name } boxSize={ 6 } mr={ 2 }/> <TokenLogo data={ token } boxSize={ 6 } mr={ 2 }/>
<AddressLink fontWeight="700" hash={ token.address } type="token" alias={ tokenString }/> <AddressLink fontWeight="700" hash={ token.address } type="token" alias={ tokenString }/>
</Flex> </Flex>
<Flex alignItems="center" pl={ 8 }> <Flex alignItems="center" pl={ 8 }>
......
...@@ -27,7 +27,7 @@ const ERC20TokensTableItem = ({ ...@@ -27,7 +27,7 @@ const ERC20TokensTableItem = ({
<Tr> <Tr>
<Td verticalAlign="middle"> <Td verticalAlign="middle">
<Flex alignItems="center"> <Flex alignItems="center">
<TokenLogo hash={ token.address } name={ token.name } boxSize={ 6 } mr={ 2 }/> <TokenLogo data={ token } boxSize={ 6 } mr={ 2 }/>
<AddressLink fontWeight="700" hash={ token.address } type="token" alias={ tokenString }/> <AddressLink fontWeight="700" hash={ token.address } type="token" alias={ tokenString }/>
</Flex> </Flex>
</Td> </Td>
......
import { Flex, HStack, Text } from '@chakra-ui/react'; import { Flex, HStack, Text } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { AddressTokenBalance } from 'types/api/address'; import type { AddressTokenBalance } from 'types/api/address';
...@@ -12,14 +13,17 @@ import TokenLogo from 'ui/shared/TokenLogo'; ...@@ -12,14 +13,17 @@ import TokenLogo from 'ui/shared/TokenLogo';
type Props = AddressTokenBalance; type Props = AddressTokenBalance;
const ERC721TokensListItem = ({ token, value }: Props) => { const ERC721TokensListItem = ({ token, value }: Props) => {
const router = useRouter();
const hash = router.query.hash?.toString() || '';
const tokenString = [ token.name, token.symbol && `(${ token.symbol })` ].filter(Boolean).join(' '); const tokenString = [ token.name, token.symbol && `(${ token.symbol })` ].filter(Boolean).join(' ');
return ( return (
<ListItemMobile rowGap={ 2 }> <ListItemMobile rowGap={ 2 }>
<Flex alignItems="center" width="100%"> <Flex alignItems="center" width="100%">
<TokenLogo hash={ token.address } name={ token.name } boxSize={ 6 } mr={ 2 }/> <TokenLogo data={ token } boxSize={ 6 } mr={ 2 }/>
<AddressLink fontWeight="700" hash={ token.address } type="token" alias={ tokenString }/> <AddressLink fontWeight="700" hash={ hash } tokenHash={ token.address } type="address_token" alias={ tokenString }/>
</Flex> </Flex>
<Flex alignItems="center" pl={ 8 }> <Flex alignItems="center" pl={ 8 }>
<AddressLink hash={ token.address } type="address" truncation="constant"/> <AddressLink hash={ token.address } type="address" truncation="constant"/>
......
import { Tr, Td, Flex } from '@chakra-ui/react'; import { Tr, Td, Flex } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { AddressTokenBalance } from 'types/api/address'; import type { AddressTokenBalance } from 'types/api/address';
...@@ -14,15 +15,17 @@ const ERC721TokensTableItem = ({ ...@@ -14,15 +15,17 @@ const ERC721TokensTableItem = ({
token, token,
value, value,
}: Props) => { }: Props) => {
const router = useRouter();
const hash = router.query.hash?.toString() || '';
const tokenString = [ token.name, token.symbol && `(${ token.symbol })` ].filter(Boolean).join(' '); const tokenString = [ token.name, token.symbol && `(${ token.symbol })` ].filter(Boolean).join(' ');
return ( return (
<Tr> <Tr>
<Td verticalAlign="middle"> <Td verticalAlign="middle">
<Flex alignItems="center"> <Flex alignItems="center">
<TokenLogo hash={ token.address } name={ token.name } boxSize={ 6 } mr={ 2 }/> <TokenLogo data={ token } boxSize={ 6 } mr={ 2 }/>
<AddressLink fontWeight="700" hash={ token.address } type="token" alias={ tokenString }/> <AddressLink fontWeight="700" hash={ hash } tokenHash={ token.address } type="address_token" alias={ tokenString }/>
</Flex> </Flex>
</Td> </Td>
<Td verticalAlign="middle"> <Td verticalAlign="middle">
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment