(env: string | undefined): DataType | null => {
+ try {
+ return JSON.parse(env || 'null') as DataType | null;
+ } catch (error) {
+ return null;
+ }
+};
+
+export const getExternalAssetFilePath = (envName: string) => {
+ const parsedValue = getEnvValue(envName);
+
+ if (!parsedValue) {
+ return;
+ }
+
+ return buildExternalAssetFilePath(envName, parsedValue);
+};
+
+export const buildExternalAssetFilePath = (name: string, value: string) => {
+ try {
+ const fileName = name.replace(/^NEXT_PUBLIC_/, '').replace(/_URL$/, '').toLowerCase();
+
+ const fileExtension = getAssetFileExtension(value);
+ if (!fileExtension) {
+ throw new Error('Cannot get file path');
+ }
+ return `/assets/configs/${ fileName }.${ fileExtension }`;
+ } catch (error) {
+ return;
+ }
+};
+
+function getAssetFileExtension(value: string) {
+ try {
+ const url = new URL(value);
+ return url.pathname.match(regexp.FILE_EXTENSION)?.[1];
+ } catch (error) {
+ return parseEnvJson(value) ? 'json' : undefined;
+ }
+}
diff --git a/explorer/frontend/configs/envs/.env.arbitrum b/explorer/frontend/configs/envs/.env.arbitrum
new file mode 100644
index 000000000..269cb33f8
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.arbitrum
@@ -0,0 +1,65 @@
+# Set of ENVs for Arbitrum One network explorer
+# https://arbitrum.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=arbitrum"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=arbitrum.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swapscout','icon':'swap','dappId':'swapscout'},{'text':'Revokescout','icon':'integration/partial','dappId':'revokescout'},{'text':'Payment link','icon':'payment_link','dappId':'peanut-protocol'}]
+NEXT_PUBLIC_DEX_POOLS_ENABLED=true
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/arbitrum-one.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x37c798810d49ba132b40efe7f4fdf6806a8fc58226bb5e185ddc91f896577abf
+NEXT_PUBLIC_HAS_CONTRACT_AUDIT_REPORTS=true
+NEXT_PUBLIC_HAS_USER_OPS=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_operational_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['rgba(27, 74, 221, 1)']}
+NEXT_PUBLIC_HOMEPAGE_STATS=['latest_batch','average_block_time','total_operational_txs','wallet_addresses','gas_tracker']
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_LOGOUT_URL=https://blockscout-arbitrum.us.auth0.com/v2/logout
+NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE=Joined recent campaigns? Mint your Merit Badge here
+NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL=https://gist.githubusercontent.com/0xdeval/b27a4aecaad513fa033e37430a4f9a47/raw/3a2fa70068ea27c3e6d58dc4cdbeb732968d62f3/revokescout-banner.html
+NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL=https://arbitrum.blockscout.com/apps/revokescout?chainId=42161
+NEXT_PUBLIC_MARKETPLACE_ENABLED=true
+NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID=appGkvtmKI7fXE4Vs
+NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
+NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}]
+NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/pools']
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=ETH
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Moralis','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/moralis.png','baseUrl':'https://moralis.com/','paths':{'token':'/chain/arbitrum/token/price'}},{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/arbitrum/pools'}}]
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/arbitrum-one-icon-light.svg
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/arbitrum-one-icon-dark.svg
+NEXT_PUBLIC_NETWORK_ID=42161
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/arbitrum-one-logo-light.svg
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/arbitrum-one-logo-dark.svg
+NEXT_PUBLIC_NETWORK_NAME=Arbitrum One
+NEXT_PUBLIC_NETWORK_RPC_URL=https://arbitrum-one.publicnode.com
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Arbitrum One
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/arbitrum-one.png
+NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://eth.blockscout.com
+NEXT_PUBLIC_ROLLUP_PARENT_CHAIN={'baseUrl':'https://eth.blockscout.com','currency':{'name':'Ether','symbol':'ETH','decimals':18},'isTestnet':false,'id':1,'name':'Ethereum Mainnet','rpcUrls':['https://eth.drpc.org']}
+NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME=Ethereum
+NEXT_PUBLIC_ROLLUP_TYPE=arbitrum
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://arbitrum.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
+NEXT_PUBLIC_XSTAR_SCORE_URL=https://docs.xname.app/the-solution-adaptive-proof-of-humanity-on-blockchain/xhs-scoring-algorithm?utm_source=blockscout&utm_medium=address
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.arbitrum_nova b/explorer/frontend/configs/envs/.env.arbitrum_nova
new file mode 100644
index 000000000..2888565d7
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.arbitrum_nova
@@ -0,0 +1,42 @@
+# Set of ENVs for Arbitrum One network explorer
+# https://arbitrum.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=arbitrum"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=arbitrum-nova.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x37c798810d49ba132b40efe7f4fdf6806a8fc58226bb5e185ddc91f896577abf
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND=rgba(27, 74, 221, 1)
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_LOGOUT_URL=https://blockscout-arbitrum.us.auth0.com/v2/logout
+NEXT_PUBLIC_MARKETPLACE_ENABLED=false
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=ETH
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/arbitrum/pools'}}]
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/arbitrum-nova-icon.svg
+NEXT_PUBLIC_NETWORK_ID=42170
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/arbitrum-nova.svg
+NEXT_PUBLIC_NETWORK_NAME=Arbitrum Nova
+NEXT_PUBLIC_NETWORK_RPC_URL=https://arbitrum.llamarpc.com
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Arbitrum Nova
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/arbitrum-nova.png
+NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://eth.blockscout.com
+NEXT_PUBLIC_ROLLUP_TYPE=arbitrum
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.arbitrum_sepolia b/explorer/frontend/configs/envs/.env.arbitrum_sepolia
new file mode 100644
index 000000000..f324dacdf
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.arbitrum_sepolia
@@ -0,0 +1,52 @@
+# Set of ENVs for Arbitrum Sepolia network explorer
+# https://arbitrum-sepolia.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=arbitrum_sepolia"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=arbitrum-sepolia.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/arbitrum-sepolia.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xb730960249381c72588024f5e213abd8e032d968aeb9629103e70677b0850bfa
+NEXT_PUBLIC_HAS_USER_OPS=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_operational_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['rgba(27, 74, 221, 1)']}
+NEXT_PUBLIC_HOMEPAGE_STATS=['latest_batch','average_block_time','total_operational_txs','wallet_addresses','gas_tracker']
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_LOGOUT_URL=https://blockscout-arbitrum.us.auth0.com/v2/logout
+NEXT_PUBLIC_MARKETPLACE_ENABLED=false
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=ETH
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/arbitrum-sepolia.svg
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/arbitrum-sepolia-dark.svg
+NEXT_PUBLIC_NETWORK_ID=421614
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/arbitrum-sepolia.svg
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/arbitrum-sepolia-dark.svg
+NEXT_PUBLIC_NETWORK_NAME=Arbitrum Sepolia
+NEXT_PUBLIC_NETWORK_RPC_URL=https://sepolia-rollup.arbitrum.io/rpc
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Arbitrum Sepolia
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/arbitrum-sepolia.png
+NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://eth-sepolia.blockscout.com
+NEXT_PUBLIC_ROLLUP_PARENT_CHAIN={'baseUrl':'https://eth-sepolia.blockscout.com','currency':{'name':'Ether','symbol':'ETH','decimals':18},'isTestnet':true,'id':11155111,'name':'Sepolia','rpcUrls':['https://eth-sepolia.public.blastapi.io']}
+NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME=Sepolia
+NEXT_PUBLIC_ROLLUP_TYPE=arbitrum
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://arbitrum-sepolia.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.base b/explorer/frontend/configs/envs/.env.base
new file mode 100644
index 000000000..fa0829c56
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.base
@@ -0,0 +1,74 @@
+# Set of ENVs for Base Mainnet network explorer
+# https://base.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=base"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=base.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swapscout','icon':'swap','dappId':'swapscout'},{'text':'Revokescout','icon':'integration/partial','dappId':'revokescout'},{'text':'Payment link','icon':'payment_link','dappId':'peanut-protocol'}]
+NEXT_PUBLIC_DEX_POOLS_ENABLED=true
+NEXT_PUBLIC_FAULT_PROOF_ENABLED=true
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/eth.json
+NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/base-mainnet.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GAS_REFUEL_PROVIDER_CONFIG={'name': 'Need gas?', 'url_template': 'https://smolrefuel.com/?outboundChain={chainId}&partner=blockscout&utm_source=blockscout&disableBridges=true', 'dapp_id': 'smol-refuel', 'logo': 'https://blockscout-content.s3.amazonaws.com/smolrefuel-logo-action-button.png'}
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xfd5c5dae7b69fe29e61d19b9943e688aa0f1be1e983c4fba8fe985f90ff69d5f
+NEXT_PUBLIC_HAS_CONTRACT_AUDIT_REPORTS=true
+NEXT_PUBLIC_HAS_USER_OPS=true
+NEXT_PUBLIC_HIDE_INDEXING_ALERT_INT_TXS=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'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_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_LOGOUT_URL=https://basechain.us.auth0.com/v2/logout
+NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE=Joined recent campaigns? Mint your Merit Badge here
+NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL=https://gist.githubusercontent.com/0xdeval/974c47f86a3158c1a86b092ae2f044b3/raw/abcc7e02150cd85d4974503a0357162c0a2c35a9/merits-banner.html
+NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL=https://base.blockscout.com/apps/swapscout
+NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json
+NEXT_PUBLIC_MARKETPLACE_ENABLED=true
+NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID=appGkvtmKI7fXE4Vs
+NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-security-reports/default.json
+NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
+NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_METASUITES_ENABLED=true
+NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'},{'name': 'zapper', 'url_template': 'https://zapper.xyz/account/{address}', 'logo': 'https://blockscout-content.s3.amazonaws.com/zapper-icon.png'}]
+NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
+NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/pools']
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Moralis','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/moralis.png','baseUrl':'https://moralis.com/','paths':{'token':'/chain/base/token/price'}},{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/base/pools'}},{'title':'Tenderly','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/tenderly.png','baseUrl':'https://dashboard.tenderly.co','paths':{'tx':'/tx/base'}},{'title':'3xpl','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/3xpl.png','baseUrl':'https://3xpl.com/','paths':{'tx':'/base/transaction','address':'/base/address'}}]
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/base.svg
+NEXT_PUBLIC_NETWORK_ID=8453
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/base.svg
+NEXT_PUBLIC_NETWORK_NAME=Base Mainnet
+NEXT_PUBLIC_NETWORK_RPC_URL=https://mainnet.base.org/
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Mainnet
+NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/base-mainnet.png
+NEXT_PUBLIC_OTHER_LINKS=[{'url':'https://base.drpc.org?ref=559183','text':'Public RPC'}]
+NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://eth.blockscout.com/
+NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL=https://bridge.base.org/withdraw
+NEXT_PUBLIC_ROLLUP_TYPE=optimistic
+NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-base.safe.global
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://base.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE=gradient_avatar
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES=[{'name':'Rarible','collection_url':'https://rarible.com/collection/base/{hash}/items','instance_url':'https://rarible.com/token/base/{hash}:{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/rarible.png'},{'name':'OpenSea','collection_url':'https://opensea.io/assets/base/{hash}','instance_url':'https://opensea.io/assets/base/{hash}/{id}','logo_url':'https://opensea.io/static/images/logos/opensea-logo.svg'}, {'name':'MagicEden','collection_url':'https://magiceden.io/collections/base/{hash}','instance_url':'https://magiceden.io/item-details/base/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/magiceden.png'}]
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
+NEXT_PUBLIC_XSTAR_SCORE_URL=https://docs.xname.app/the-solution-adaptive-proof-of-humanity-on-blockchain/xhs-scoring-algorithm?utm_source=blockscout&utm_medium=address
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.blackfort_testnet b/explorer/frontend/configs/envs/.env.blackfort_testnet
new file mode 100644
index 000000000..2f6c3cdee
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.blackfort_testnet
@@ -0,0 +1,46 @@
+# Set of ENVs for BXN Testnet network explorer
+# https://blackfort-testnet.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=blackfort_testnet"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=testnet.blackfortscan.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/blackfort-testnet.json
+NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/blackfort.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x12b9dc860aaa12918dece27124775d334fe245f9fdb7feddf622b180a605e0a4
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['linear-gradient(92deg, rgb(3, 150, 254) 0.24%, rgb(36, 209, 245) 98.31%)']}
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_MARKETPLACE_ENABLED=false
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=TBXN
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=TBXN
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/blackfort.svg
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/blackfort-dark.svg
+NEXT_PUBLIC_NETWORK_ID=4888
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/blackfort.svg
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/blackfort-dark.svg
+NEXT_PUBLIC_NETWORK_NAME=BXN Testnet
+NEXT_PUBLIC_NETWORK_RPC_URL=https://rpc.blackfort.network/testnet/rpc
+NEXT_PUBLIC_NETWORK_SHORT_NAME=BXN Testnet
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/blackfort.png
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://testnet.blackfortscan.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.celo_alfajores b/explorer/frontend/configs/envs/.env.celo_alfajores
new file mode 100644
index 000000000..42aea78fc
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.celo_alfajores
@@ -0,0 +1,51 @@
+# Set of ENVs for Celo Alfajores network explorer
+# https://celo-alfajores.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=celo_alfajores"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=celo-alfajores.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CELO_ENABLED=true
+NEXT_PUBLIC_CELO_L2_UPGRADE_BLOCK=26369280
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/celo.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GAS_TRACKER_ENABLED=false
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x9767ce30754afad2a3279b9df2d13257f467c3dad4e0e601271e66d16dfd1641
+NEXT_PUBLIC_HAS_USER_OPS=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['rgba(252, 255, 82, 1)'],'text_color':['rgba(0, 0, 0, 1)']}
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_MARKETPLACE_ENABLED=false
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=CELO
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=CELO
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/celo-icon-light.svg
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/celo-icon-dark.svg
+NEXT_PUBLIC_NETWORK_ID=44787
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/celo-logo-light.svg
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/celo-logo-dark.svg
+NEXT_PUBLIC_NETWORK_MULTIPLE_GAS_CURRENCIES=true
+NEXT_PUBLIC_NETWORK_NAME=Celo Alfajores
+NEXT_PUBLIC_NETWORK_RPC_URL=https://alfajores-forno.celo-testnet.org
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Alfajores
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/celo.png
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://celo-alfajores.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_BLOCK_HIDDEN_FIELDS=['burnt_fees']
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.eth b/explorer/frontend/configs/envs/.env.eth
new file mode 100644
index 000000000..8a32019f8
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.eth
@@ -0,0 +1,70 @@
+# Set of ENVs for Ethereum network explorer
+# https://eth.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=eth"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=eth.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED=true
+NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swapscout','icon':'swap','dappId':'swapscout'},{'text':'Revokescout','icon':'integration/partial','dappId':'revokescout'},{'text':'Payment link','icon':'payment_link','dappId':'peanut-protocol'}]
+NEXT_PUBLIC_DEX_POOLS_ENABLED=true
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/eth.json
+NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/eth-mainnet.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GAS_REFUEL_PROVIDER_CONFIG={'name': 'Need gas?', 'url_template': 'https://smolrefuel.com/?outboundChain={chainId}&partner=blockscout&utm_source=blockscout&disableBridges=true', 'dapp_id': 'smol-refuel', 'logo': 'https://blockscout-content.s3.amazonaws.com/smolrefuel-logo-action-button.png'}
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xd01175f1efa23f36c5579b3c13e2bbd0885017643a7efef5cbcb6b474384dfa8
+NEXT_PUBLIC_HAS_BEACON_CHAIN=true
+NEXT_PUBLIC_HAS_CONTRACT_AUDIT_REPORTS=true
+NEXT_PUBLIC_HAS_USER_OPS=true
+NEXT_PUBLIC_HIDE_INDEXING_ALERT_BLOCKS=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs', 'coin_price', 'market_cap']
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_LOGOUT_URL=https://ethereum-mainnet.us.auth0.com/v2/logout
+NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE=Joined recent campaigns? Mint your Merit Badge here
+NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL=https://gist.githubusercontent.com/0xdeval/b27a4aecaad513fa033e37430a4f9a47/raw/3a2fa70068ea27c3e6d58dc4cdbeb732968d62f3/revokescout-banner.html
+NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL=https://eth.blockscout.com/apps/revokescout?chainId=1
+NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json
+NEXT_PUBLIC_MARKETPLACE_ENABLED=true
+NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID=appGkvtmKI7fXE4Vs
+NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-security-reports/default.json
+NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
+NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_METASUITES_ENABLED=true
+NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'},{'name': 'zapper', 'url_template': 'https://zapper.xyz/account/{address}', 'logo': 'https://blockscout-content.s3.amazonaws.com/zapper-icon.png'}]
+NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
+NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/pools']
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Moralis','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/moralis.png','baseUrl':'https://moralis.com/','paths':{'token':'/chain/ethereum/token/price'}},{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/eth/pools'}},{'title':'Etherscan','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/etherscan.png','baseUrl':'https://etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}, {'title':'Blockchair','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/blockchair.png','baseUrl':'https://blockchair.com/','paths':{'tx':'/ethereum/transaction','address':'/ethereum/address','token':'/ethereum/erc-20/token','block':'/ethereum/block'}},{'title':'Sentio','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/sentio.png','baseUrl':'https://app.sentio.xyz/','paths':{'tx':'/tx/1','address':'/contract/1'}}, {'title':'Tenderly','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/tenderly.png','baseUrl':'https://dashboard.tenderly.co','paths':{'tx':'/tx/mainnet'}}, {'title':'0xPPL','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/0xPPL.png','baseUrl':'https://0xppl.com','paths':{'tx':'/Ethereum/tx','address':'/','token':'/c/Ethereum'}}, {'title':'3xpl','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/3xpl.png','baseUrl':'https://3xpl.com/','paths':{'tx':'/ethereum/transaction','address':'/ethereum/address'}} ]
+NEXT_PUBLIC_NETWORK_ID=1
+NEXT_PUBLIC_NETWORK_NAME=Ethereum
+NEXT_PUBLIC_NETWORK_RPC_URL=https://rpc.eth.gateway.fm
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Ethereum
+NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/eth.jpg
+NEXT_PUBLIC_OTHER_LINKS=[{'url':'https://eth.drpc.org?ref=559183','text':'Public RPC'}]
+NEXT_PUBLIC_REWARDS_SERVICE_API_HOST=https://merits.blockscout.com
+NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-mainnet.safe.global
+NEXT_PUBLIC_SAVE_ON_GAS_ENABLED=true
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://eth.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES=[{'name':'OpenSea','collection_url':'https://opensea.io/assets/ethereum/{hash}','instance_url':'https://opensea.io/assets/ethereum/{hash}/{id}','logo_url':'https://opensea.io/static/images/logos/opensea-logo.svg'},{'name':'Rarible','collection_url':'https://rarible.com/collection/{hash}/items','instance_url':'https://rarible.com/token/{hash}:{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/rarible.png'},{'name':'Blur','collection_url':'https://blur.io/eth/collection/{hash}','instance_url':'https://blur.io/eth/asset/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/blur.png'},{'name':'MagicEden','collection_url':'https://magiceden.io/collections/ethereum/{hash}','instance_url':'https://magiceden.io/item-details/ethereum/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/magiceden.png'}]
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
+NEXT_PUBLIC_XSTAR_SCORE_URL=https://docs.xname.app/the-solution-adaptive-proof-of-humanity-on-blockchain/xhs-scoring-algorithm?utm_source=blockscout&utm_medium=address
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.eth_goerli b/explorer/frontend/configs/envs/.env.eth_goerli
new file mode 100644
index 000000000..09cab1823
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.eth_goerli
@@ -0,0 +1,56 @@
+# Set of ENVs for Göerli network explorer
+# https://eth-goerli.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=eth_goerli"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_AD_ADBUTLER_CONFIG_DESKTOP={ 'id': '610111', 'w': '728', 'h': '90' }
+NEXT_PUBLIC_AD_ADBUTLER_CONFIG_MOBILE={ 'id': '610112', 'w': '300', 'h': '100' }
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=eth-goerli.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swapscout','icon':'swap','dappId':'swapscout'},{'text':'Payment link','icon':'payment_link','dappId':'peanut-protocol'},{'text':'Get gas','icon':'gas','dappId':'smol-refuel'}]
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/eth-goerli.json
+NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/eth-goerli.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x5fd9325045efc08eef82ff15f59c765cb6df34a30d77b4f4db70ba59a226106a
+NEXT_PUBLIC_HAS_CONTRACT_AUDIT_REPORTS=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_LOGOUT_URL=https://blockscout-goerli.us.auth0.com/v2/logout
+NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE=Ethereum Goerli testnet has been deprecated. Migrate to Sepolia and Holesky testnets.
+NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json
+NEXT_PUBLIC_MARKETPLACE_ENABLED=true
+NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
+NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Etherscan','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/etherscan.png','logo':'https://github.com/blockscout/frontend-configs/blob/main/configs/explorer-logos/etherscan.png?raw=true','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}, {'title':'Tenderly','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/tenderly.png','baseUrl':'https://dashboard.tenderly.co','paths':{'tx':'/tx/goerli'}}]
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/goerli.svg
+NEXT_PUBLIC_NETWORK_ID=5
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/goerli.svg
+NEXT_PUBLIC_NETWORK_NAME=Göerli
+NEXT_PUBLIC_NETWORK_RPC_URL=https://rpc.ankr.com/eth_goerli
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Göerli
+NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/eth-goerli.png
+NEXT_PUBLIC_OTHER_LINKS=[{'url':'https://goerli.drpc.org?ref=559183','text':'Public RPC'}]
+NEXT_PUBLIC_STATS_API_HOST=https://stats-goerli.k8s-dev.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES=[{'name':'OpenSea','collection_url':'https://testnets.opensea.io/assets/goerli/{hash}','instance_url':'https://testnets.opensea.io/assets/goerli/{hash}/{id}','logo_url':'https://opensea.io/static/images/logos/opensea-logo.svg'},{'name':'Rarible','collection_url':'https://testnet.rarible.com/collection/{hash}/items','instance_url':'https://testnet.rarible.com/token/{hash}:{id}','logo_url':'https://theme.zdassets.com/theme_assets/10342982/b874f2d764307e820514e17252b783f0f344ede6.svg'}]
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.eth_sepolia b/explorer/frontend/configs/envs/.env.eth_sepolia
new file mode 100644
index 000000000..1fa16df76
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.eth_sepolia
@@ -0,0 +1,73 @@
+# Set of ENVs for Sepolia network explorer
+# https://eth-sepolia.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=eth_sepolia"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_AD_ADBUTLER_CONFIG_DESKTOP={ "id": "632019", "width": "728", "height": "90" }
+NEXT_PUBLIC_AD_ADBUTLER_CONFIG_MOBILE={ "id": "632018", "width": "320", "height": "100" }
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=eth-sepolia.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED=true
+NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swapscout','icon':'swap','dappId':'swapscout'},{'text':'Payment link','icon':'payment_link','dappId':'peanut-protocol'}]
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/eth.json
+NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/sepolia.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xbf69c7abc4fee283b59a9633dadfdaedde5c5ee0fba3e80a08b5b8a3acbd4363
+NEXT_PUBLIC_HAS_BEACON_CHAIN=true
+NEXT_PUBLIC_HAS_USER_OPS=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['rgba(51, 53, 67, 1)'],'text_color':['rgba(165, 252, 122, 1)']}
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_LOGOUT_URL=https://blockscout-goerli.us.auth0.com/v2/logout
+NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE=Joined recent campaigns? Mint your Merit Badge here
+NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL=https://gist.githubusercontent.com/0xdeval/b27a4aecaad513fa033e37430a4f9a47/raw/3a2fa70068ea27c3e6d58dc4cdbeb732968d62f3/revokescout-banner.html,
+NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL=https://revoke.blockscout.com?utm_source=blockscout&utm_medium=eth-sepolia,
+NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json
+NEXT_PUBLIC_MARKETPLACE_ENABLED=true
+NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID=appGkvtmKI7fXE4Vs
+NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-security-reports/default.json
+NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
+NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_METASUITES_ENABLED=true
+NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'},{'name': 'zapper', 'url_template': 'https://zapper.xyz/account/{address}', 'logo': 'https://blockscout-content.s3.amazonaws.com/zapper-icon.png'}]
+NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
+NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/apps']
+NEXT_PUBLIC_NAVIGATION_LAYOUT=horizontal
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/sepolia-testnet/pools'}},{'title':'Etherscan','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/etherscan.png','baseUrl':'https://sepolia.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}, {'title':'Tenderly','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/tenderly.png','baseUrl':'https://dashboard.tenderly.co','paths':{'tx':'/tx/sepolia'}} ]
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/sepolia.png
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/sepolia.png
+NEXT_PUBLIC_NETWORK_ID=11155111
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/sepolia.svg
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/sepolia.svg
+NEXT_PUBLIC_NETWORK_NAME=Sepolia
+NEXT_PUBLIC_NETWORK_RPC_URL=https://eth-sepolia.public.blastapi.io
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Sepolia
+NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/sepolia-testnet.png
+NEXT_PUBLIC_OTHER_LINKS=[{'url':'https://sepolia.drpc.org?ref=559183','text':'Public RPC'}]
+NEXT_PUBLIC_REWARDS_SERVICE_API_HOST=https://merits.blockscout.com
+NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-sepolia.safe.global
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://eth-sepolia.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
+NEXT_PUBLIC_XSTAR_SCORE_URL=https://docs.xname.app/the-solution-adaptive-proof-of-humanity-on-blockchain/xhs-scoring-algorithm?utm_source=blockscout&utm_medium=address
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.filecoin b/explorer/frontend/configs/envs/.env.filecoin
new file mode 100644
index 000000000..b2a17bb2d
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.filecoin
@@ -0,0 +1,51 @@
+# Set of ENVs for Filecoin Virtual Machine network explorer
+# https://filecoin.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=filecoin"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=filecoin.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Revokescout','icon':'integration/partial','dappId':'revokescout'}]
+NEXT_PUBLIC_DEX_POOLS_ENABLED=true
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/filecoin-mainnet.json
+NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/fvm.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x5abb6212c1802402b828ed20c2bd4d4a6153b8bee68a5259cba3c8d7a7c6b775
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs', 'coin_price', 'market_cap']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['linear-gradient(237deg, rgb(26, 58, 150) 14.83%, rgb(111, 223, 164) 132.56%)'],'text_color':['rgba(255, 255, 255, 1)']}
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_LOGOUT_URL=https://blockscout-filecoin.us.auth0.com/v2/logout
+NEXT_PUBLIC_MARKETPLACE_ENABLED=false
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/pools']
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=FIL
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=FIL
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/filecoin/pools'}}]
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/filecoin-icon-dark.svg
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/filecoin-icon-light.svg
+NEXT_PUBLIC_NETWORK_ID=314
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/filecoin-logo-dark.svg
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/filecoin-logo-light.svg
+NEXT_PUBLIC_NETWORK_NAME=Filecoin Virtual Machine
+NEXT_PUBLIC_NETWORK_RPC_URL=https://api.node.glif.io
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Filecoin Virtual Machine
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/filecoin.png
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://filecoin.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE=gradient_avatar
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.garnet b/explorer/frontend/configs/envs/.env.garnet
new file mode 100644
index 000000000..eaf25df51
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.garnet
@@ -0,0 +1,56 @@
+# Set of ENVs for Garnet Testnet network explorer
+# https://explorer.garnetchain.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=garnet"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_AD_BANNER_PROVIDER=none
+NEXT_PUBLIC_AD_TEXT_PROVIDER=none
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=explorer.garnetchain.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/redstone.json
+NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/redstone.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x5b0ba69f2cf5fbc6da96b6cf475c5521f7a385efd9d68673f69c1fc54f737a52
+NEXT_PUBLIC_HAS_MUD_FRAMEWORK=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['rgb(169, 31, 47)']}
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_LOGOUT_URL=https://redstone-lattice.us.auth0.com/v2/logout
+NEXT_PUBLIC_MARKETPLACE_ENABLED=false
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/garnet.svg
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/garnet-dark.svg
+NEXT_PUBLIC_NETWORK_ID=17069
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/garnet.svg
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/garnet-dark.svg
+NEXT_PUBLIC_NETWORK_NAME=Garnet Testnet
+NEXT_PUBLIC_NETWORK_RPC_URL=https://rpc.garnetchain.com
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Garnet Testnet
+NEXT_PUBLIC_OG_DESCRIPTION=Redstone is the home for onchain games, worlds, and other MUD applications
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/garnet.png
+NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://eth-holesky.blockscout.com/
+NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL=https://garnet.qry.live/withdraw
+NEXT_PUBLIC_ROLLUP_TYPE=optimistic
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://explorer.garnetchain.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.gnosis b/explorer/frontend/configs/envs/.env.gnosis
new file mode 100644
index 000000000..257e950f7
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.gnosis
@@ -0,0 +1,76 @@
+# Set of ENVs for Gnosis chain network explorer
+# https://gnosis.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=gnosis"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=gnosis.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_BEACON_CHAIN_CURRENCY_SYMBOL=GNO
+NEXT_PUBLIC_BRIDGED_TOKENS_BRIDGES=[{'type':'omni','title':'OmniBridge','short_title':'OMNI'},{'type':'amb','title':'Arbitrary Message Bridge','short_title':'AMB'}]
+NEXT_PUBLIC_BRIDGED_TOKENS_CHAINS=[{'id':'1','title':'Ethereum','short_title':'ETH','base_url':'https://eth.blockscout.com/token/'},{'id':'56','title':'Binance Smart Chain','short_title':'BSC','base_url':'https://bscscan.com/token/'},{'id':'99','title':'POA','short_title':'POA','base_url':'https://blockscout.com/poa/core/token/'}]
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED=true
+NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swapscout','icon':'swap','dappId':'swapscout'},{'text':'Revokescout','icon':'integration/partial','dappId':'revokescout'},{'text':'Payment link','icon':'payment_link','dappId':'peanut-protocol'}]
+NEXT_PUBLIC_DEX_POOLS_ENABLED=true
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/gnosis-chain-mainnet.json
+NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/gnosis.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GAS_REFUEL_PROVIDER_CONFIG={'name': 'Need gas?', 'url_template': 'https://smolrefuel.com/?outboundChain={chainId}&partner=blockscout&utm_source=blockscout&disableBridges=true', 'dapp_id': 'smol-refuel', 'logo': 'https://blockscout-content.s3.amazonaws.com/smolrefuel-logo-action-button.png'}
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x082762f95047d39d612daafec832f88163f3815fde4ddd8944f2a5198a396e0f
+NEXT_PUBLIC_HAS_BEACON_CHAIN=true
+NEXT_PUBLIC_HAS_CONTRACT_AUDIT_REPORTS=true
+NEXT_PUBLIC_HAS_USER_OPS=true
+NEXT_PUBLIC_HIDE_INDEXING_ALERT_INT_TXS=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs', 'tvl']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['rgb(46, 74, 60)'],'text_color':['rgb(255, 255, 255)']}
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_LOGOUT_URL=https://login.blockscout.com/v2/logout
+NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE=Joined recent campaigns? Mint your Merit Badge here
+NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL=https://gist.githubusercontent.com/0xdeval/b27a4aecaad513fa033e37430a4f9a47/raw/3a2fa70068ea27c3e6d58dc4cdbeb732968d62f3/revokescout-banner.html
+NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL=https://gnosis.blockscout.com/apps/revokescout?chainId=100
+NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json
+NEXT_PUBLIC_MARKETPLACE_ENABLED=true
+NEXT_PUBLIC_MARKETPLACE_GRAPH_LINKS_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/refs/heads/main/configs/marketplace-subgraph-links/subgraph-links.json
+NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID=appGkvtmKI7fXE4Vs
+NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-security-reports/default.json
+NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
+NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_METASUITES_ENABLED=true
+NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'},{'name': 'zapper', 'url_template': 'https://zapper.xyz/account/{address}', 'logo': 'https://blockscout-content.s3.amazonaws.com/zapper-icon.png'}]
+NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
+NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/pools']
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=XDAI
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=XDAI
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/xdai/pools'}},{'title':'Tenderly','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/tenderly.png','baseUrl':'https://dashboard.tenderly.co','paths':{'tx':'/tx/gnosis-chain'}},{'title':'3xpl','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/3xpl.png','baseUrl':'https://3xpl.com/','paths':{'tx':'/gnosis-chain/transaction','address':'/gnosis-chain/address'}}]
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/gnosis.svg
+NEXT_PUBLIC_NETWORK_ID=100
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/gnosis.svg
+NEXT_PUBLIC_NETWORK_NAME=Gnosis chain
+NEXT_PUBLIC_NETWORK_RPC_URL=https://rpc.gnosischain.com
+NEXT_PUBLIC_NETWORK_SECONDARY_COIN_SYMBOL=GNO
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Gnosis chain
+NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/gnosis-chain-mainnet.png
+NEXT_PUBLIC_OTHER_LINKS=[{'url':'https://gnosis.drpc.org?ref=559183','text':'Public RPC'}]
+NEXT_PUBLIC_REWARDS_SERVICE_API_HOST=https://merits.blockscout.com
+NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-gnosis-chain.safe.global
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://gnosis.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
+NEXT_PUBLIC_XSTAR_SCORE_URL=https://docs.xname.app/the-solution-adaptive-proof-of-humanity-on-blockchain/xhs-scoring-algorithm?utm_source=blockscout&utm_medium=address
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.immutable b/explorer/frontend/configs/envs/.env.immutable
new file mode 100644
index 000000000..810203d7c
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.immutable
@@ -0,0 +1,54 @@
+# Set of ENVs for Immutable network explorer
+# https://explorer.immutable.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=immutable"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_AD_BANNER_PROVIDER=none
+NEXT_PUBLIC_AD_TEXT_PROVIDER=none
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=explorer.immutable.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swapscout','icon':'swap','dappId':'swapscout'},{'text':'Revokescout','icon':'integration/partial','dappId':'revokescout'}]
+NEXT_PUBLIC_DEX_POOLS_ENABLED=true
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/immutable-mainnet.json
+NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/immutable.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x6166cece570f4731ccc94c2d17d854ce88496cd3b48e03b537959992ab6685c8
+NEXT_PUBLIC_HAS_CONTRACT_AUDIT_REPORTS=true
+NEXT_PUBLIC_HELIA_VERIFIED_FETCH_ENABLED=false
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['no-repeat center/100% 100% url(https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-skins/immutable.jpg)'],'text_color':['rgba(19, 19, 19, 1)']}
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_LOGOUT_URL=https://blockscout-immutable.us.auth0.com/v2/logout
+NEXT_PUBLIC_MARKETPLACE_ENABLED=false
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/pools']
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=IMX
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=IMX
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/immutable-zkevm/pools'}}]
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/immutable-short.svg
+NEXT_PUBLIC_NETWORK_ID=13371
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/immutable.svg
+NEXT_PUBLIC_NETWORK_NAME=Immutable
+NEXT_PUBLIC_NETWORK_RPC_URL=https://rpc.immutable.com/
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Immutable
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/immutable.png
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://explorer.immutable.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_BLOCK_HIDDEN_FIELDS=["miner"]
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.jest b/explorer/frontend/configs/envs/.env.jest
new file mode 100644
index 000000000..abe2107a8
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.jest
@@ -0,0 +1,52 @@
+# Set of ENVs for Jest unit tests
+
+# app configuration
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+
+# blockchain parameters
+NEXT_PUBLIC_NETWORK_NAME=Blockscout
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Blockscout
+NEXT_PUBLIC_NETWORK_ID=1
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation
+NEXT_PUBLIC_NETWORK_RPC_URL=https://localhost:1111
+NEXT_PUBLIC_IS_TESTNET=true
+
+# api configuration
+NEXT_PUBLIC_API_HOST=localhost
+NEXT_PUBLIC_API_PORT=3003
+NEXT_PUBLIC_API_BASE_PATH=/
+
+# ui config
+## homepage
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs','coin_price','market_cap']
+NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND=
+## sidebar
+NEXT_PUBLIC_NETWORK_LOGO=
+NEXT_PUBLIC_NETWORK_LOGO_DARK=
+NEXT_PUBLIC_NETWORK_ICON=
+NEXT_PUBLIC_NETWORK_ICON_DARK=
+NEXT_PUBLIC_FEATURED_NETWORKS=
+## footer
+NEXT_PUBLIC_FOOTER_LINKS=
+NEXT_PUBLIC_GIT_TAG=v1.0.11
+## misc
+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'}}]
+
+# app features
+NEXT_PUBLIC_APP_INSTANCE=jest
+NEXT_PUBLIC_APP_ENV=testing
+NEXT_PUBLIC_MARKETPLACE_CONFIG_URL=https://localhost:3000/marketplace-config.json
+NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://localhost:3000/marketplace-submit-form
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_AUTH_URL=http://localhost:3100
+NEXT_PUBLIC_LOGOUT_URL=https://blockscoutcom.us.auth0.com/v2/logout
+NEXT_PUBLIC_AUTH0_CLIENT_ID=xxx
+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
diff --git a/explorer/frontend/configs/envs/.env.localhost b/explorer/frontend/configs/envs/.env.localhost
new file mode 100644
index 000000000..3956c0d11
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.localhost
@@ -0,0 +1,39 @@
+# Set of ENVs for local network explorer
+# frontend app URL - https://localhost:3000/
+# API URL - https://localhost:3001/
+
+# app configuration
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+
+# blockchain parameters
+NEXT_PUBLIC_NETWORK_NAME=POA
+NEXT_PUBLIC_NETWORK_SHORT_NAME=POA
+NEXT_PUBLIC_NETWORK_ID=99
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=POA
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=POA
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation
+NEXT_PUBLIC_NETWORK_RPC_URL=https://core.poa.network
+
+# api configuration
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=localhost
+NEXT_PUBLIC_API_PROTOCOL=http
+NEXT_PUBLIC_API_PORT=3001
+
+# ui config
+## homepage
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs','coin_price','market_cap']
+## sidebar
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/eth-goerli.json
+## footer
+## misc
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Anyblock','baseUrl':'https://explorer.anyblock.tools','paths':{'tx':'/ethereum/poa/core/transaction','address':'/ethereum/poa/core/address'}}]
+
+# app features
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_AUTH_URL=http://localhost:3000
+NEXT_PUBLIC_LOGOUT_URL=https://blockscoutcom.us.auth0.com/v2/logout
diff --git a/explorer/frontend/configs/envs/.env.main b/explorer/frontend/configs/envs/.env.main
new file mode 100644
index 000000000..17a181515
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.main
@@ -0,0 +1,75 @@
+# Set of ENVs for Sepolia network explorer
+# https://eth-sepolia.k8s-dev.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=main"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs-test.k8s-dev.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=eth-sepolia.k8s-dev.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info-test.k8s-dev.blockscout.com
+NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED=true
+NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swapscout','icon':'swap','dappId':'swapscout'},{'text':'Payment link','icon':'payment_link','dappId':'peanut-protocol'}]
+NEXT_PUBLIC_DEX_POOLS_ENABLED=true
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/eth-sepolia.json
+NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/sepolia.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GAS_REFUEL_PROVIDER_CONFIG={'name': 'Need gas?', 'url_template': 'https://smolrefuel.com/?outboundChain={chainId}', 'dapp_id': 'smol-refuel', 'logo': 'https://blockscout-content.s3.amazonaws.com/smolrefuel-logo-action-button.png'}
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x93e00d4d48cf0dc229f5102e18277fa1bb6130d5b319697a87698a35cf67f706
+NEXT_PUBLIC_HAS_BEACON_CHAIN=true
+NEXT_PUBLIC_HAS_USER_OPS=true
+NEXT_PUBLIC_HELIA_VERIFIED_FETCH_ENABLED=false
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['rgba(51, 53, 67, 1)'],'text_color':['rgba(165, 252, 122, 1)']}
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_LOGOUT_URL=https://blockscout-goerli.us.auth0.com/v2/logout
+NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json
+NEXT_PUBLIC_MARKETPLACE_ENABLED=true
+NEXT_PUBLIC_MARKETPLACE_GRAPH_LINKS_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/refs/heads/marketplace-graph-test/test-configs/marketplace-graph-links.json
+NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID=appGkvtmKI7fXE4Vs
+NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/test-configs/marketplace-security-report-mock.json
+NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
+NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata-test.k8s-dev.blockscout.com
+NEXT_PUBLIC_METASUITES_ENABLED=true
+NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'},{'name': 'zapper', 'url_template': 'https://zapper.xyz/account/{address}?utm_source=blockscout&utm_medium=address', 'logo': 'https://blockscout-content.s3.amazonaws.com/zapper-icon.png'}]
+NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens-rs-test.k8s-dev.blockscout.com
+NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/pools']
+NEXT_PUBLIC_NAVIGATION_LAYOUT=vertical
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Etherscan','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/etherscan.png', 'baseUrl':'https://sepolia.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}, {'title':'Tenderly','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/tenderly.png','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/tenderly.png','baseUrl':'https://dashboard.tenderly.co','paths':{'tx':'/tx/sepolia'}} ]
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/sepolia.png
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/sepolia.png
+NEXT_PUBLIC_NETWORK_ID=11155111
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/sepolia.svg
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/sepolia.svg
+NEXT_PUBLIC_NETWORK_NAME=Sepolia
+NEXT_PUBLIC_NETWORK_RPC_URL=https://eth-sepolia.public.blastapi.io
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Sepolia
+NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/sepolia-testnet.png
+NEXT_PUBLIC_OTHER_LINKS=[{'url':'https://sepolia.drpc.org?ref=559183','text':'Public RPC'}]
+NEXT_PUBLIC_REWARDS_SERVICE_API_HOST=https://points.k8s-dev.blockscout.com
+NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-sepolia.safe.global
+NEXT_PUBLIC_SAVE_ON_GAS_ENABLED=true
+NEXT_PUBLIC_SEO_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://eth-sepolia.k8s-dev.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE=nouns
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer-test.k8s-dev.blockscout.com
+NEXT_PUBLIC_XSTAR_SCORE_URL=https://docs.xname.app/the-solution-adaptive-proof-of-humanity-on-blockchain/xhs-scoring-algorithm?utm_source=blockscout&utm_medium=address
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.mekong b/explorer/frontend/configs/envs/.env.mekong
new file mode 100644
index 000000000..39c048182
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.mekong
@@ -0,0 +1,34 @@
+# Set of ENVs for Mekong network explorer
+# https://mekong.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=mekong"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=mekong.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x7c7d9e09a5e0e6441a81efe57dbcf08848cd18a1f4238e28152faead390066a4
+NEXT_PUBLIC_HAS_BEACON_CHAIN=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=ETH
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_ID=7078815900
+NEXT_PUBLIC_NETWORK_NAME=Mekong
+NEXT_PUBLIC_NETWORK_RPC_URL=https://rpc.mekong.ethpandaops.io
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Mekong
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.neon_devnet b/explorer/frontend/configs/envs/.env.neon_devnet
new file mode 100644
index 000000000..89aca9295
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.neon_devnet
@@ -0,0 +1,46 @@
+# Set of ENVs for Neon Devnet network explorer
+# https://neon-devnet.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=neon_devnet"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=neon-devnet.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/neon-devnet.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x0716b7a70a1c3b83f731084d7c1449148392512318c2ce0fd812d029204707b5
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['linear-gradient(0, rgb(223, 66, 171), rgb(176, 40, 209))'],'text_color':['rgba(255, 255, 255, 1)']}
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_LOGOUT_URL=https://blockscout-neon.us.auth0.com/v2/logout
+NEXT_PUBLIC_MARKETPLACE_ENABLED=false
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=NEON
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=NEON
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/neon-short.svg
+NEXT_PUBLIC_NETWORK_ID=245022926
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/neon.svg
+NEXT_PUBLIC_NETWORK_NAME=Neon Devnet
+NEXT_PUBLIC_NETWORK_RPC_URL=https://devnet.neonevm.org
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Neon
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/neon-devnet.png
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://neon-devnet.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_TX_EXTERNAL_TRANSACTIONS_CONFIG={'chain_name':'Solana Devnet','chain_logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/refs/heads/main/configs/network-icons/solana.svg','explorer_url_template':'https://solscan.io/tx/{hash}?cluster=devnet'}
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.optimism b/explorer/frontend/configs/envs/.env.optimism
new file mode 100644
index 000000000..3cf0bf057
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.optimism
@@ -0,0 +1,74 @@
+# Set of ENVs for OP Mainnet network explorer
+# https://optimism.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=optimism"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=optimism.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swapscout','icon':'swap','dappId':'swapscout'},{'text':'Revokescout','icon':'integration/partial','dappId':'revokescout'},{'text':'Payment link','icon':'payment_link','dappId':'peanut-protocol'}]
+NEXT_PUBLIC_DEX_POOLS_ENABLED=true
+NEXT_PUBLIC_FAULT_PROOF_ENABLED=true
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/optimism-mainnet.json
+NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/optimism.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GAS_REFUEL_PROVIDER_CONFIG={'name': 'Need gas?', 'url_template': 'https://smolrefuel.com/?outboundChain={chainId}&partner=blockscout&utm_source=blockscout&disableBridges=true', 'dapp_id': 'smol-refuel', 'logo': 'https://blockscout-content.s3.amazonaws.com/smolrefuel-logo-action-button.png'}
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x97f34a4cf685e365460dd38dbe16e092d8e4cc4b6ac779e3abcf4c18df6b1329
+NEXT_PUBLIC_HAS_CONTRACT_AUDIT_REPORTS=true
+NEXT_PUBLIC_HAS_USER_OPS=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs', 'coin_price', 'market_cap', 'secondary_coin_price']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['linear-gradient(90deg, rgb(232, 52, 53) 0%, rgb(139, 28, 232) 100%)'],'text_color':['rgb(255, 255, 255)']}
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_LOGOUT_URL=https://optimism-goerli.us.auth0.com/v2/logout
+NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE=Joined recent campaigns? Mint your Merit Badge here
+NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL=https://gist.githubusercontent.com/0xdeval/974c47f86a3158c1a86b092ae2f044b3/raw/abcc7e02150cd85d4974503a0357162c0a2c35a9/merits-banner.html
+NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL=https://optimism.blockscout.com/apps/swapscout
+NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json
+NEXT_PUBLIC_MARKETPLACE_ENABLED=true
+NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID=appGkvtmKI7fXE4Vs
+NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-security-reports/default.json
+NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
+NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_METASUITES_ENABLED=true
+NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}]
+NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
+NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/pools']
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Moralis','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/moralis.png','baseUrl':'https://moralis.com/','paths':{'token':'/chain/optimism/token/price'}},{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/optimism/pools'}}, {'title':'Tenderly','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/tenderly.png','baseUrl':'https://dashboard.tenderly.co','paths':{'tx':'/tx/optimistic'}},{'title':'3xpl','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/3xpl.png','baseUrl':'https://3xpl.com/','paths':{'tx':'/optimism/transaction','address':'/optimism/address'}}]
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/optimism-mainnet-light.svg
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/optimism-mainnet-dark.svg
+NEXT_PUBLIC_NETWORK_ID=10
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/optimism.svg
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/optimism.svg
+NEXT_PUBLIC_NETWORK_NAME=OP Mainnet
+NEXT_PUBLIC_NETWORK_RPC_URL=https://mainnet.optimism.io
+NEXT_PUBLIC_NETWORK_SECONDARY_COIN_SYMBOL=OP
+NEXT_PUBLIC_NETWORK_SHORT_NAME=OP Mainnet
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/optimism-mainnet.png
+NEXT_PUBLIC_OTHER_LINKS=[{'url':'https://optimism.drpc.org?ref=559183','text':'Public RPC'}]
+NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://eth.blockscout.com/
+NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL=https://app.optimism.io/bridge/withdraw
+NEXT_PUBLIC_ROLLUP_TYPE=optimistic
+NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-optimism.safe.global
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://optimism.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
+NEXT_PUBLIC_WEB3_WALLETS=['token_pocket', 'metamask']
+NEXT_PUBLIC_XSTAR_SCORE_URL=https://docs.xname.app/the-solution-adaptive-proof-of-humanity-on-blockchain/xhs-scoring-algorithm?utm_source=blockscout&utm_medium=address
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.optimism_interop_0 b/explorer/frontend/configs/envs/.env.optimism_interop_0
new file mode 100644
index 000000000..0bc99d1c5
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.optimism_interop_0
@@ -0,0 +1,50 @@
+# Set of ENVs for OP Interop Alpha 0 network explorer
+# https://optimism-interop-alpha-0.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=optimism_interop_0"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_AD_BANNER_PROVIDER=none
+NEXT_PUBLIC_AD_TEXT_PROVIDER=none
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=optimism-interop-alpha-0.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_FAULT_PROOF_ENABLED=true
+NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/optimism.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['linear-gradient(90deg, rgb(232, 52, 53) 0%, rgb(139, 28, 232) 100%)'],'text_color':['rgb(255, 255, 255)']}
+NEXT_PUBLIC_INTEROP_ENABLED=true
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/optimism.svg
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/optimism.svg
+NEXT_PUBLIC_NETWORK_ID=420120000
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/optimism.svg
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/optimism.svg
+NEXT_PUBLIC_NETWORK_NAME=OP Interop Alpha 0
+NEXT_PUBLIC_NETWORK_RPC_URL=https://interop-alpha-0.optimism.io
+NEXT_PUBLIC_NETWORK_SHORT_NAME=OP Interop Alpha 0
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://eth-sepolia.blockscout.com/
+NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL=https://bridge.interop-alpha-0.optimism.io
+NEXT_PUBLIC_ROLLUP_OUTPUT_ROOTS_ENABLED=false
+NEXT_PUBLIC_ROLLUP_TYPE=optimistic
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://optimism-interop-alpha-0.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
+NEXT_PUBLIC_WEB3_WALLETS=['token_pocket', 'metamask']
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.optimism_sepolia b/explorer/frontend/configs/envs/.env.optimism_sepolia
new file mode 100644
index 000000000..313881ba9
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.optimism_sepolia
@@ -0,0 +1,56 @@
+# Set of ENVs for OP Sepolia network explorer
+# https://optimism-sepolia.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=optimism_sepolia"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=optimism-sepolia.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_FAULT_PROOF_ENABLED=true
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/optimism-sepolia.json
+NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/optimism.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x59d26836041ab35169bdce431d68d070b7b8acb589fa52e126e6c828b6ece5e9
+NEXT_PUBLIC_HAS_USER_OPS=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['linear-gradient(90deg, rgb(232, 52, 53) 0%, rgb(139, 28, 232) 100%)'],'text_color':['rgb(255, 255, 255)']}
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_LOGOUT_URL=https://optimism-goerli.us.auth0.com/v2/logout
+NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE=Build faster with the Superchain Dev Console : Get testnet ETH and tools to help you build, launch, and grow your app on the Superchain
+NEXT_PUBLIC_MARKETPLACE_ENABLED=false
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Tenderly','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/tenderly.png','baseUrl':'https://dashboard.tenderly.co','paths':{'tx':'/tx/optimistic-sepolia'}}]
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/optimism.svg
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/optimism.svg
+NEXT_PUBLIC_NETWORK_ID=11155420
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/optimism.svg
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/optimism.svg
+NEXT_PUBLIC_NETWORK_NAME=OP Sepolia
+NEXT_PUBLIC_NETWORK_RPC_URL=https://sepolia.optimism.io
+NEXT_PUBLIC_NETWORK_SHORT_NAME=OP Sepolia
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://eth-sepolia.blockscout.com/
+NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL=https://app.optimism.io/bridge/withdraw
+NEXT_PUBLIC_ROLLUP_TYPE=optimistic
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://optimism-sepolia.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
+NEXT_PUBLIC_WEB3_WALLETS=['token_pocket', 'metamask']
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.polygon b/explorer/frontend/configs/envs/.env.polygon
new file mode 100644
index 000000000..8f5e0b69f
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.polygon
@@ -0,0 +1,63 @@
+# Set of ENVs for Polygon Mainnet network explorer
+# https://polygon.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=polygon"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_AD_ADBUTLER_CONFIG_DESKTOP={ "id": "632019", "width": "728", "height": "90" }
+NEXT_PUBLIC_AD_ADBUTLER_CONFIG_MOBILE={ "id": "632018", "width": "320", "height": "100" }
+NEXT_PUBLIC_AD_BANNER_PROVIDER=adbutler
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=polygon.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swapscout','icon':'swap','dappId':'swapscout'},{'text':'Revokescout','icon':'integration/partial','dappId':'revokescout'},{'text':'Payment link','icon':'payment_link','dappId':'peanut-protocol'},{'text':'Get gas','icon':'gas','dappId':'smol-refuel'}]
+NEXT_PUBLIC_DEX_POOLS_ENABLED=true
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/polygon-mainnet.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x25fcb396fc8652dcd0040f677a1dcc6fecff390ecafc815894379a3f254f1aa9
+NEXT_PUBLIC_HAS_USER_OPS=true
+NEXT_PUBLIC_HIDE_INDEXING_ALERT_BLOCKS=true
+NEXT_PUBLIC_HIDE_INDEXING_ALERT_INT_TXS=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['linear-gradient(122deg, rgba(162, 41, 197, 1) 0%, rgba(123, 63, 228, 1) 100%)'],'text_color':['rgba(255, 255, 255, 1)']}
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_LOGOUT_URL=https://blockscout-polygon.us.auth0.com/v2/logout
+NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL=https://gist.githubusercontent.com/0xdeval/974c47f86a3158c1a86b092ae2f044b3/raw/abcc7e02150cd85d4974503a0357162c0a2c35a9/merits-banner.html
+NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL=https://polygon.blockscout.com/apps/swapscout
+NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json
+NEXT_PUBLIC_MARKETPLACE_ENABLED=true
+NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID=appGkvtmKI7fXE4Vs
+NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
+NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_METASUITES_ENABLED=true
+NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
+NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/pools']
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=POL
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=POL
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Moralis','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/moralis.png','baseUrl':'https://moralis.com/','paths':{'token':'/chain/polygon/token/price'}},{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/polygon_pos/pools'}}]
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/polygon-short.svg
+NEXT_PUBLIC_NETWORK_ID=137
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/polygon.svg
+NEXT_PUBLIC_NETWORK_NAME=Polygon Mainnet
+NEXT_PUBLIC_NETWORK_RPC_URL=https://polygon-rpc.com
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Polygon
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/polygon-mainnet.png
+NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-polygon.safe.global
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://polygon.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
+NEXT_PUBLIC_WEB3_WALLETS=['token_pocket', 'metamask']
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.pw b/explorer/frontend/configs/envs/.env.pw
new file mode 100644
index 000000000..6229341ea
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.pw
@@ -0,0 +1,60 @@
+# Set of ENVs for Playwright components tests
+
+# app configuration
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3100
+
+# blockchain parameters
+NEXT_PUBLIC_NETWORK_NAME=Blockscout
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Blockscout
+NEXT_PUBLIC_NETWORK_ID=1
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_RPC_URL=https://localhost:1111
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation
+
+# api configuration
+NEXT_PUBLIC_API_PROTOCOL=http
+NEXT_PUBLIC_API_HOST=localhost
+NEXT_PUBLIC_API_PORT=3003
+NEXT_PUBLIC_API_BASE_PATH=/
+
+# ui config
+## homepage
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs','coin_price','market_cap']
+## sidebar
+## footer
+NEXT_PUBLIC_GIT_TAG=v1.0.11
+## views
+NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES=[{'name':'OpenSea','collection_url':'https://opensea.io/assets/ethereum/{hash}','instance_url':'https://opensea.io/assets/ethereum/{hash}/{id}','logo_url':'http://localhost:3000/nft-marketplace-logo.png'},{'name':'LooksRare','collection_url':'https://looksrare.org/collections/{hash}','instance_url':'https://looksrare.org/collections/{hash}/{id}','logo_url':'http://localhost:3000/nft-marketplace-logo.png'}]
+## misc
+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_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.blockscout.com/%23address={hash}&blockscout=eth-goerli.blockscout.com'}]
+NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE=
+
+# app features
+NEXT_PUBLIC_APP_ENV=testing
+NEXT_PUBLIC_APP_INSTANCE=pw
+NEXT_PUBLIC_MARKETPLACE_ENABLED=true
+NEXT_PUBLIC_MARKETPLACE_CONFIG_URL=https://localhost:3000/marketplace-config.json
+NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://localhost:3000/marketplace-submit-form
+NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://localhost:3000/marketplace-suggest-ideas-form
+NEXT_PUBLIC_AD_BANNER_PROVIDER=slise
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_AUTH_URL=http://localhost:3100
+NEXT_PUBLIC_LOGOUT_URL=https://blockscoutcom.us.auth0.com/v2/logout
+NEXT_PUBLIC_AUTH0_CLIENT_ID=xxx
+NEXT_PUBLIC_STATS_API_HOST=http://localhost:3004
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=http://localhost:3005
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=http://localhost:3006
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=http://localhost:3007
+NEXT_PUBLIC_NAME_SERVICE_API_HOST=http://localhost:3008
+NEXT_PUBLIC_REWARDS_SERVICE_API_HOST=http://localhost:3009
+NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=xxx
+NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=xxx
+NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT=['base16','bech32']
+NEXT_PUBLIC_VIEWS_ADDRESS_BECH_32_PREFIX=tom
+NEXT_PUBLIC_HELIA_VERIFIED_FETCH_ENABLED=false
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.rari_testnet b/explorer/frontend/configs/envs/.env.rari_testnet
new file mode 100644
index 000000000..8d64dd5e5
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.rari_testnet
@@ -0,0 +1,41 @@
+# Set of ENVs for Rari Testnet network explorer
+# https://rari-testnet.cloud.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=rari_testnet"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_AD_BANNER_PROVIDER=slise
+NEXT_PUBLIC_AD_TEXT_PROVIDER=coinzilla
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=rari-testnet.cloud.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_COLOR_THEME_DEFAULT=light
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xbf69c7abc4fee283b59a9633dadfdaedde5c5ee0fba3e80a08b5b8a3acbd4363
+NEXT_PUBLIC_HAS_BEACON_CHAIN=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND=radial-gradient(farthest-corner at 0% 0%, rgba(183, 148, 244, 0.80) 0%, rgba(0, 163, 196, 0.80) 100%)
+NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR=rgb(255,255,255)
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_NAVIGATION_HIDDEN_LINKS=[]
+NEXT_PUBLIC_NAVIGATION_LAYOUT=vertical
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=ETH
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_ID=1
+NEXT_PUBLIC_NETWORK_NAME=Rari Testnet
+NEXT_PUBLIC_NETWORK_RPC_URL=https://rari-testnet.calderachain.xyz/partner-blockscout
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Rari Testnet
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=false
+NEXT_PUBLIC_OTHER_LINKS=[]
+NEXT_PUBLIC_ROLLUP_DA_CELESTIA_NAMESPACE=0x00000000000000000000000000000000000000ca1de12a9905be97beaf
+NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://arbitrum-sepolia.blockscout.com/
+NEXT_PUBLIC_ROLLUP_TYPE=arbitrum
+NEXT_PUBLIC_SEO_ENHANCED_DATA_ENABLED=false
+NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE=jazzicon
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.rootstock_testnet b/explorer/frontend/configs/envs/.env.rootstock_testnet
new file mode 100644
index 000000000..bbc89a77f
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.rootstock_testnet
@@ -0,0 +1,49 @@
+# Set of ENVs for Rootstock Testnet network explorer
+# https://rootstock-testnet.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=rootstock_testnet"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=rootstock-testnet.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/rsk-testnet.json
+NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/rootstock.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x98b25020fa6551a439dfee58fb16ca11d9e93d4cdf15f3f07b697cf08cf11643
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['rgb(255, 145, 0)'],'text_color':['rgb(255, 255, 255)']}
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_LOGOUT_URL=https://rootstock.us.auth0.com/v2/logout
+NEXT_PUBLIC_MARKETPLACE_ENABLED=false
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=tRBTC
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=tRBTC
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Tenderly','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/tenderly.png','baseUrl':'https://dashboard.tenderly.co','paths':{'tx':'/tx/rsk-testnet'}}]
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/rootstock-short.svg
+NEXT_PUBLIC_NETWORK_ID=31
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/rootstock.svg
+NEXT_PUBLIC_NETWORK_NAME=Rootstock Testnet
+NEXT_PUBLIC_NETWORK_RPC_URL=https://public-node.testnet.rsk.co
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Rootstock
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/rootstock-testnet.png
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://rootstock-testnet.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_BLOCK_HIDDEN_FIELDS=['burnt_fees','total_reward','nonce']
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.scroll_sepolia b/explorer/frontend/configs/envs/.env.scroll_sepolia
new file mode 100644
index 000000000..aa17a2465
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.scroll_sepolia
@@ -0,0 +1,46 @@
+# Set of ENVs for Scroll Sepolia Testnet network explorer
+# https://scroll-sepolia.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=scroll_sepolia"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=scroll-sepolia.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/scroll-testnet.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xa0d22caf6217a488b1e97b646c5ed88e8a3020a607bcd1f3fe8d4c430bb19ad5
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['rgba(255, 238, 218, 1)'],'text_color':['rgba(25, 6, 2, 1)']}
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/scroll.svg
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/scroll-dark.svg
+NEXT_PUBLIC_NETWORK_ID=534351
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/scroll.svg
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/scroll-dark.svg
+NEXT_PUBLIC_NETWORK_NAME=Scroll Sepolia Testnet
+NEXT_PUBLIC_NETWORK_RPC_URL=https://sepolia-rpc.scroll.io
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Scroll Sepolia Testnet
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/scroll-testnet.png
+NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://eth-sepolia.blockscout.com
+NEXT_PUBLIC_ROLLUP_TYPE=scroll
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://scroll-sepolia.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_CONTRACT_LANGUAGE_FILTERS=['solidity','vyper','yul','scilla']
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.shibarium b/explorer/frontend/configs/envs/.env.shibarium
new file mode 100644
index 000000000..e96f2fb19
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.shibarium
@@ -0,0 +1,68 @@
+# Set of ENVs for Shibarium network explorer
+# https://www.shibariumscan.io
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=shibarium"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_AD_BANNER_PROVIDER=hype
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=www.shibariumscan.io
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_APP_INSTANCE=shibarium_mainnet
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Revokescout','icon':'integration/partial','dappId':'revokescout'}]
+NEXT_PUBLIC_DEX_POOLS_ENABLED=true
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/shibarium-mainnet.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GAS_REFUEL_PROVIDER_CONFIG={'name': 'Need gas?', 'url_template': 'https://smolrefuel.com/?outboundChain={chainId}&partner=blockscout&utm_source=blockscout&disableBridges=true', 'dapp_id': 'smol-refuel', 'logo': 'https://blockscout-content.s3.amazonaws.com/smolrefuel-logo-action-button.png'}
+NEXT_PUBLIC_GAS_TRACKER_UNITS=['gwei', 'usd']
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xce531d29c0c469fb00b443b8091b8c059b4f13d7e025dd0ef843401d02b9a1a9
+NEXT_PUBLIC_HAS_CONTRACT_AUDIT_REPORTS=true
+NEXT_PUBLIC_HIDE_INDEXING_ALERT_INT_TXS=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs', 'coin_price', 'market_cap']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['linear-gradient(180deg, rgba(224, 111, 44, 1) 0%, rgba(228, 144, 52, 1) 100%)'],'text_color':['rgba(255, 255, 255, 1)']}
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_LOGOUT_URL=https://shibarium.us.auth0.com/v2/logout
+NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE=Joined recent campaigns? Mint your Merit Badge here
+NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL=https://gist.githubusercontent.com/0xdeval/b27a4aecaad513fa033e37430a4f9a47/raw/3a2fa70068ea27c3e6d58dc4cdbeb732968d62f3/revokescout-banner.html
+NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL=https://www.shibariumscan.io/apps/revokescout?chainId=109
+NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json
+NEXT_PUBLIC_MARKETPLACE_ENABLED=true
+NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID=appGkvtmKI7fXE4Vs
+NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-security-reports/default.json
+NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
+NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
+NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/pools']
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=BONE
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=BONE
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/shibarium/pools'}}]
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/shibarium-short.png
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/shibarium-short.png
+NEXT_PUBLIC_NETWORK_ID=109
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/shibarium-light.png
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/shibarium-dark.png
+NEXT_PUBLIC_NETWORK_NAME=Shibarium
+NEXT_PUBLIC_NETWORK_RPC_URL=https://www.shibrpc.com
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Shibarium
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/shibarium-mainnet.png
+NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://eth.blockscout.com/
+NEXT_PUBLIC_ROLLUP_TYPE=shibarium
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://www.shibariumscan.io
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_BLOCK_HIDDEN_FIELDS=['miner']
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.stability_testnet b/explorer/frontend/configs/envs/.env.stability_testnet
new file mode 100644
index 000000000..864283bdf
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.stability_testnet
@@ -0,0 +1,56 @@
+# Set of ENVs for Stability Testnet network explorer
+# https://stability-testnet.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=stability_testnet"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=explorer.testnet.stabilityprotocol.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/stability-testnet.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x38125475465a4113a216448af2c9570d0e2c25ef313f8cfbef74f1daad7a97b5
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['rgba(46, 51, 81, 1)'],'text_color':['rgba(122, 235, 246, 1)']}
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_LOGOUT_URL=https://blockscout-stability.us.auth0.com/v2/logout
+NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json
+NEXT_PUBLIC_MARKETPLACE_ENABLED=true
+NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
+NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=FREE
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=FREE
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/stability-short.svg
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/stability-short-dark.svg
+NEXT_PUBLIC_NETWORK_ID=20180427
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/stability.svg
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/stability-dark.svg
+NEXT_PUBLIC_NETWORK_NAME=Stability Testnet
+NEXT_PUBLIC_NETWORK_RPC_URL=https://free.testnet.stabilityprotocol.com
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Stability Testnet
+NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/stability.png
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://explorer.testnet.stabilityprotocol.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE=stability
+NEXT_PUBLIC_VIEWS_ADDRESS_HIDDEN_VIEWS=['top_accounts']
+NEXT_PUBLIC_VIEWS_BLOCK_HIDDEN_FIELDS=['burnt_fees','total_reward']
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VIEWS_TX_ADDITIONAL_FIELDS=['fee_per_gas']
+NEXT_PUBLIC_VIEWS_TX_HIDDEN_FIELDS=['value','fee_currency','gas_price','gas_fees','burnt_fees']
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.zilliqa_prototestnet b/explorer/frontend/configs/envs/.env.zilliqa_prototestnet
new file mode 100644
index 000000000..75830ec3a
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.zilliqa_prototestnet
@@ -0,0 +1,44 @@
+# Set of ENVs for Zilliqa EVM proto-testnet network explorer
+# https://zilliqa-prototestnet.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=zilliqa_prototestnet"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=zilliqa-prototestnet.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x3d1ded3a7924cd3256a4b1a447c9bfb194f54b9a8ceb441edb8bb01563b516db
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['linear-gradient(90deg, rgba(0, 208, 198, 1) 0.06%, rgba(43, 146, 151, 1) 99.97%)','linear-gradient(90deg, rgba(0, 208, 198, 1) 0.06%, rgba(43, 146, 151, 1) 50.02%, rgba(0, 0, 0, 1) 99.97%)'],'text_color':['rgba(255, 255, 255, 1)','rgba(255, 255, 255, 1)'],'button':{'_default':{'background':['rgba(38, 6, 124, 1)']},'_hover':{'background':['rgba(17, 4, 87, 1)']}}}
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=ZIL
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ZIL
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/zilliqa.svg
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/zilliqa-dark.svg
+NEXT_PUBLIC_NETWORK_ID=33103
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/zilliqa.svg
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/zilliqa-dark.svg
+NEXT_PUBLIC_NETWORK_NAME=Zilliqa EVM proto-testnet
+NEXT_PUBLIC_NETWORK_RPC_URL=https://api.zq2-prototestnet.zilliqa.com
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Zilliqa EVM proto-testnet
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/zilliqa.png
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE=zilliqa
+NEXT_PUBLIC_VIEWS_ADDRESS_BECH_32_PREFIX=zil
+NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT=["base16", "bech32"]
+NEXT_PUBLIC_VIEWS_CONTRACT_LANGUAGE_FILTERS=['solidity','vyper','yul','scilla']
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.zkevm b/explorer/frontend/configs/envs/.env.zkevm
new file mode 100644
index 000000000..3ee02e415
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.zkevm
@@ -0,0 +1,60 @@
+# Set of ENVs for Polygon zkEVM network explorer
+# https://zkevm.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=zkevm"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_AD_ADBUTLER_CONFIG_DESKTOP={ "id": "632019", "width": "728", "height": "90" }
+NEXT_PUBLIC_AD_ADBUTLER_CONFIG_MOBILE={ "id": "632018", "width": "320", "height": "100" }
+NEXT_PUBLIC_AD_BANNER_PROVIDER=adbutler
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=zkevm.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swapscout','icon':'swap','dappId':'swapscout'},{'text':'Revokescout','icon':'integration/partial','dappId':'revokescout'}]
+NEXT_PUBLIC_DEX_POOLS_ENABLED=true
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/zkevm.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x25fcb396fc8652dcd0040f677a1dcc6fecff390ecafc815894379a3f254f1aa9
+NEXT_PUBLIC_HAS_USER_OPS=true
+NEXT_PUBLIC_HIDE_INDEXING_ALERT_INT_TXS=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['linear-gradient(122deg, rgba(162, 41, 197, 1) 0%, rgba(123, 63, 228, 1) 100%)'],'text_color':['rgba(255, 255, 255, 1)']}
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_LOGOUT_URL=https://blockscout-polygon.us.auth0.com/v2/logout
+NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json
+NEXT_PUBLIC_MARKETPLACE_ENABLED=true
+NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
+NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_METASUITES_ENABLED=true
+NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/pools']
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=ETH
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/polygon-zkevm/pools'}}]
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/polygon-short.svg
+NEXT_PUBLIC_NETWORK_ID=1101
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/polygon.svg
+NEXT_PUBLIC_NETWORK_NAME=Polygon zkEVM
+NEXT_PUBLIC_NETWORK_RPC_URL=https://zkevm-rpc.com
+NEXT_PUBLIC_NETWORK_SHORT_NAME=zkEVM
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://eth.blockscout.com/
+NEXT_PUBLIC_ROLLUP_TYPE=zkEvm
+NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-zkevm.safe.global
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://zkevm.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
+NEXT_PUBLIC_WEB3_WALLETS=['token_pocket', 'metamask']
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.zksync b/explorer/frontend/configs/envs/.env.zksync
new file mode 100644
index 000000000..d95638f45
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.zksync
@@ -0,0 +1,61 @@
+# Set of ENVs for ZkSync Era network explorer
+# https://zksync.blockscout.com
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=zksync"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=zksync.blockscout.com
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swapscout','icon':'swap','dappId':'swapscout'},{'text':'Revokescout','icon':'integration/partial','dappId':'revokescout'},{'text':'Payment link','icon':'payment_link','dappId':'peanut-protocol'}]
+NEXT_PUBLIC_DEX_POOLS_ENABLED=true
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/zksync.json
+NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/zksync.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x79c7802ccdf3be5a49c47cc751aad351b0027e8275f6f54878eda50ee559a648
+NEXT_PUBLIC_HAS_CONTRACT_AUDIT_REPORTS=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['rgba(53, 103, 246, 1)'],'text_color':['rgba(255, 255, 255, 1)']}
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_LOGOUT_URL=https://zksync.us.auth0.com/v2/logout
+NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json
+NEXT_PUBLIC_MARKETPLACE_ENABLED=true
+NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
+NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_METASUITES_ENABLED=true
+NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}]
+NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/pools']
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=ETH
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/zksync/pools'}},{'title':'L2scan','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/zksync.png','baseUrl':'https://zksync-era.l2scan.co/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}]
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/zksync-short.svg
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/zksync-short-dark.svg
+NEXT_PUBLIC_NETWORK_ID=324
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/zksync.svg
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/zksync-dark.svg
+NEXT_PUBLIC_NETWORK_NAME=ZkSync Era
+NEXT_PUBLIC_NETWORK_RPC_URL=https://mainnet.era.zksync.io
+NEXT_PUBLIC_NETWORK_SHORT_NAME=ZkSync Era
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/zksync.png
+NEXT_PUBLIC_OTHER_LINKS=[{'url':'https://zksync.drpc.org?ref=559183','text':'Public RPC'}]
+NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://eth.blockscout.com/
+NEXT_PUBLIC_ROLLUP_TYPE=zkSync
+NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-zksync.safe.global
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://zksync.blockscout.com
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_CONTRACT_EXTRA_VERIFICATION_METHODS=none
+NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/configs/envs/.env.zora b/explorer/frontend/configs/envs/.env.zora
new file mode 100644
index 000000000..cc6711d1e
--- /dev/null
+++ b/explorer/frontend/configs/envs/.env.zora
@@ -0,0 +1,65 @@
+# Set of ENVs for Zora Mainnet network explorer
+# https://explorer.zora.energy
+# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=zora"
+
+# Local ENVs
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+
+# Instance ENVs
+NEXT_PUBLIC_AD_BANNER_PROVIDER=none
+NEXT_PUBLIC_AD_TEXT_PROVIDER=none
+NEXT_PUBLIC_ADDRESS_USERNAME_TAG={'api_url_template': 'https://api.zora.co/discover/user/{address}', 'tag_link_template': 'https://zora.co/{username}', 'tag_icon': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/zora-zorb.png', 'tag_bg_color': 'rgba(0,0,0)', 'tag_text_color': 'rgba(255,255,255)'}
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_HOST=explorer.zora.energy
+NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
+NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swap','icon':'swap','dappId':'uniswap'},{'text':'Revokescout','icon':'integration/partial','dappId':'revokescout'}]
+NEXT_PUBLIC_DEX_POOLS_ENABLED=true
+NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/zora.json
+NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x6d54c0226a57f5bc854f8aa589bb15113388f984f318c9e1b2722115e4e35873
+NEXT_PUBLIC_HAS_CONTRACT_AUDIT_REPORTS=true
+NEXT_PUBLIC_HAS_USER_OPS=true
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['linear-gradient(89deg, rgb(63, 36, 22) 0.56%, rgb(44, 56, 105) 98.31%)']}
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_LOGOUT_URL=https://zora-blockscout.us.auth0.com/v2/logout
+NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE=Joined recent campaigns? Mint your Merit Badge here
+NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL=https://gist.githubusercontent.com/0xdeval/b27a4aecaad513fa033e37430a4f9a47/raw/3a2fa70068ea27c3e6d58dc4cdbeb732968d62f3/revokescout-banner.html
+NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL=https://explorer.zora.energy/apps/revokescout?chainId=7777777
+NEXT_PUBLIC_MARKETPLACE_ENABLED=true
+NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID=appGkvtmKI7fXE4Vs
+NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
+NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
+NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
+NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/pools']
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/zora-network/pools'}}]
+NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/zora.svg
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/zora-dark.svg
+NEXT_PUBLIC_NETWORK_ID=7777777
+NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/zora.svg
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/zora-dark.svg
+NEXT_PUBLIC_NETWORK_NAME=Zora Mainnet
+NEXT_PUBLIC_NETWORK_RPC_URL=https://rpc.zora.energy
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Zora Mainnet
+NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/zora-mainnet.png
+NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://eth.blockscout.com/
+NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL=https://bridge.zora.energy
+NEXT_PUBLIC_ROLLUP_TYPE=optimistic
+NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
+NEXT_PUBLIC_STATS_API_HOST=https://explorer.zora.energy
+NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
+NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
diff --git a/explorer/frontend/decs.d.ts b/explorer/frontend/decs.d.ts
new file mode 100644
index 000000000..0f623b644
--- /dev/null
+++ b/explorer/frontend/decs.d.ts
@@ -0,0 +1,2 @@
+declare module 'react-identicons';
+declare module 'use-font-face-observer';
diff --git a/explorer/frontend/deploy/helmfile.yaml b/explorer/frontend/deploy/helmfile.yaml
new file mode 100644
index 000000000..199073c4a
--- /dev/null
+++ b/explorer/frontend/deploy/helmfile.yaml
@@ -0,0 +1,68 @@
+environments:
+ {{ .Environment.Name }}:
+---
+helmDefaults:
+ timeout: 600
+ kubeContext: k8s-dev
+ wait: true
+ recreatePods: false
+
+repositories:
+ # - name: blockscout-ci-cd
+ # url: https://blockscout.github.io/blockscout-ci-cd
+ - name: blockscout
+ url: https://blockscout.github.io/helm-charts
+ - name: bedag
+ url: https://bedag.github.io/helm-charts
+
+releases:
+ # Deploy review L2
+ - name: reg-secret
+ chart: bedag/raw
+ namespace: review-l2-{{ requiredEnv "GITHUB_REF_NAME_SLUG" }}
+ labels:
+ app: review-l2-{{ requiredEnv "GITHUB_REF_NAME_SLUG" }}
+ values:
+ - resources:
+ - apiVersion: v1
+ data:
+ .dockerconfigjson: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/dockerRegistryCreds
+ kind: Secret
+ metadata:
+ name: regcred
+ type: kubernetes.io/dockerconfigjson
+ - name: bs-stack
+ chart: blockscout/blockscout-stack
+ version: 1.*.*
+ namespace: review-l2-{{ requiredEnv "GITHUB_REF_NAME_SLUG" }}
+ labels:
+ app: review-l2-{{ requiredEnv "GITHUB_REF_NAME_SLUG" }}
+ values:
+ - values/review-l2/values.yaml.gotmpl
+ - global:
+ env: "review"
+ # Deploy review
+ - name: reg-secret
+ chart: bedag/raw
+ namespace: review-{{ requiredEnv "GITHUB_REF_NAME_SLUG" }}
+ labels:
+ app: review-{{ requiredEnv "GITHUB_REF_NAME_SLUG" }}
+ values:
+ - resources:
+ - apiVersion: v1
+ data:
+ .dockerconfigjson: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/dockerRegistryCreds
+ kind: Secret
+ metadata:
+ name: regcred
+ type: kubernetes.io/dockerconfigjson
+ - name: bs-stack
+ chart: blockscout/blockscout-stack
+ version: 1.*.*
+ namespace: review-{{ requiredEnv "GITHUB_REF_NAME_SLUG" }}
+ labels:
+ app: review-{{ requiredEnv "GITHUB_REF_NAME_SLUG" }}
+ values:
+ - values/review/values.yaml.gotmpl
+ - global:
+ env: "review"
diff --git a/explorer/frontend/deploy/scripts/build_sprite.sh b/explorer/frontend/deploy/scripts/build_sprite.sh
new file mode 100755
index 000000000..5eace1725
--- /dev/null
+++ b/explorer/frontend/deploy/scripts/build_sprite.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+
+icons_dir="./icons"
+target_dir="./public/icons"
+
+yarn icons build -i $icons_dir -o $target_dir --optimize
+
+create_registry_file() {
+ # Create a temporary file to store the registry
+ local registry_file="$target_dir/registry.json"
+
+ # Start the JSON array
+ echo "[]" > "$registry_file"
+
+ # Detect OS and set appropriate stat command
+ get_file_size() {
+ local file="$1"
+ if [[ "$OSTYPE" == "darwin"* ]]; then
+ # macOS
+ stat -f%z "$file"
+ else
+ # Linux and others
+ stat -c%s "$file"
+ fi
+ }
+
+ # Function to process each file
+ process_file() {
+ local file="$1"
+ local relative_path="${file#$icons_dir/}"
+ local file_size=$(get_file_size "$file")
+
+ # Create a temporary file with the new entry
+ jq --arg name "$relative_path" --arg size "$file_size" \
+ '. + [{"name": $name, "file_size": ($size|tonumber)}]' \
+ "$registry_file" > "${registry_file}.tmp"
+
+ # Move the temporary file back
+ mv "${registry_file}.tmp" "$registry_file"
+ }
+
+ # Find all SVG files and process them
+ find "$icons_dir" -type f -name "*.svg" | while read -r file; do
+ process_file "$file"
+ done
+}
+
+# Skip hash creation and renaming for playwright environment
+if [ "$NEXT_PUBLIC_APP_ENV" != "pw" ]; then
+ # Generate hash from the sprite file
+ HASH=$(md5sum $target_dir/sprite.svg | cut -d' ' -f1 | head -c 8)
+
+ # Remove old sprite files
+ rm -f $target_dir/sprite.*.svg
+
+ # Rename the new sprite file
+ mv $target_dir/sprite.svg "$target_dir/sprite.${HASH}.svg"
+
+ export NEXT_PUBLIC_ICON_SPRITE_HASH=${HASH}
+
+ # Skip registry creation in development environment
+ # just to make the dev build faster
+ # remove this condition if you want to create the registry file in development environment
+ if [ "$NEXT_PUBLIC_APP_ENV" != "development" ]; then
+ create_registry_file
+ fi
+
+ echo "SVG sprite created: sprite.${HASH}.svg"
+else
+ echo "SVG sprite created: sprite.svg (hash skipped for playwright environment)"
+fi
\ No newline at end of file
diff --git a/explorer/frontend/deploy/scripts/collect_envs.sh b/explorer/frontend/deploy/scripts/collect_envs.sh
new file mode 100755
index 000000000..d53dc989e
--- /dev/null
+++ b/explorer/frontend/deploy/scripts/collect_envs.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+# Check if the number of arguments provided is correct
+if [ "$#" -ne 1 ]; then
+ echo "Usage: $0 "
+ exit 1
+fi
+
+input_file="$1"
+prefix="NEXT_PUBLIC_"
+
+# Function to make the environment variables registry file based on documentation file ENVS.md
+# It will read the input file, extract all prefixed string and use them as variables names
+# This variables will have dummy values assigned to them
+make_registry_file() {
+ output_file=".env.registry"
+
+ # Check if file already exists and empty its content if it does
+ if [ -f "$output_file" ]; then
+ > "$output_file"
+ fi
+
+ grep -oE "${prefix}[[:alnum:]_]+" "$input_file" | sort -u | while IFS= read -r var_name; do
+ echo "$var_name=__" >> "$output_file"
+ done
+}
+
+# Function to save build-time environment variables to .env file
+save_build-time_envs() {
+ output_file=".env"
+
+ # Check if file already exists and empty its content if it does or create a new one
+ if [ -f "$output_file" ]; then
+ > "$output_file"
+ else
+ touch "$output_file"
+ fi
+
+ env | grep "^${prefix}" | while IFS= read -r line; do
+ echo "$line" >> "$output_file"
+ done
+}
+
+make_registry_file
+save_build-time_envs
\ No newline at end of file
diff --git a/explorer/frontend/deploy/scripts/download_assets.sh b/explorer/frontend/deploy/scripts/download_assets.sh
new file mode 100755
index 000000000..a1c31d766
--- /dev/null
+++ b/explorer/frontend/deploy/scripts/download_assets.sh
@@ -0,0 +1,128 @@
+#!/bin/bash
+
+echo
+echo "⬇️ Downloading external assets..."
+
+# Check if the number of arguments provided is correct
+if [ "$#" -ne 1 ]; then
+ echo "🛑 Error: incorrect amount of arguments. Usage: $0 ."
+ exit 1
+fi
+
+# Define the directory to save the downloaded assets
+ASSETS_DIR="$1"
+
+# Define a list of environment variables containing URLs of external assets
+ASSETS_ENVS=(
+ "NEXT_PUBLIC_MARKETPLACE_CONFIG_URL"
+ "NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL"
+ "NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL"
+ "NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL"
+ "NEXT_PUBLIC_MARKETPLACE_GRAPH_LINKS_URL"
+ "NEXT_PUBLIC_FEATURED_NETWORKS"
+ "NEXT_PUBLIC_FOOTER_LINKS"
+ "NEXT_PUBLIC_NETWORK_LOGO"
+ "NEXT_PUBLIC_NETWORK_LOGO_DARK"
+ "NEXT_PUBLIC_NETWORK_ICON"
+ "NEXT_PUBLIC_NETWORK_ICON_DARK"
+ "NEXT_PUBLIC_OG_IMAGE_URL"
+)
+
+# Create the assets directory if it doesn't exist
+mkdir -p "$ASSETS_DIR"
+
+# Function to determine the target file name based on the environment variable
+get_target_filename() {
+ local env_var="$1"
+ local url="${!env_var}"
+
+ # Extract the middle part of the variable name (between "NEXT_PUBLIC_" and "_URL") in lowercase
+ local name_prefix="${env_var#NEXT_PUBLIC_}"
+ local name_suffix="${name_prefix%_URL}"
+ local name_lc="$(echo "$name_suffix" | tr '[:upper:]' '[:lower:]')"
+
+ # Check if the URL starts with "file://"
+ if [[ "$url" == file://* ]]; then
+ # Extract the local file path
+ local file_path="${url#file://}"
+ # Get the filename from the local file path
+ local filename=$(basename "$file_path")
+ # Extract the extension from the filename
+ local extension="${filename##*.}"
+ else
+ if [[ "$url" == http* ]]; then
+ # Remove query parameters from the URL and get the filename
+ local filename=$(basename "${url%%\?*}")
+ # Extract the extension from the filename
+ local extension="${filename##*.}"
+ else
+ local extension="json"
+ fi
+ fi
+
+ # Convert the extension to lowercase
+ extension=$(echo "$extension" | tr '[:upper:]' '[:lower:]')
+
+ # Construct the custom file name
+ echo "$name_lc.$extension"
+}
+
+# Function to download and save an asset
+download_and_save_asset() {
+ local env_var="$1"
+ local url="$2"
+ local filename="$3"
+ local destination="$ASSETS_DIR/$filename"
+
+ # Check if the environment variable is set
+ if [ -z "${!env_var}" ]; then
+ echo " [.] $env_var: Variable is not set. Skipping download."
+ return 1
+ fi
+
+ # Check if the URL starts with "file://"
+ if [[ "$url" == file://* ]]; then
+ # Copy the local file to the destination
+ cp "${url#file://}" "$destination"
+ else
+ # Check if the value is a URL
+ if [[ "$url" == http* ]]; then
+ # Download the asset using curl with timeouts
+ if ! curl -f -s --connect-timeout 5 --max-time 15 -o "$destination" "$url"; then
+ echo " [-] $env_var: Failed to download from $url (timeout or connection error)"
+ return 1
+ fi
+ else
+ # Convert single-quoted JSON-like content to valid JSON
+ json_content=$(echo "${!env_var}" | sed "s/'/\"/g")
+
+ # Save the JSON content to a file
+ echo "$json_content" > "$destination"
+ fi
+ fi
+
+ if [[ "$url" == file://* ]] || [[ "$url" == http* ]]; then
+ local source_name=$url
+ else
+ local source_name="raw input"
+ fi
+
+ # Check if the download was successful
+ if [ $? -eq 0 ]; then
+ echo " [+] $env_var: Successfully saved file from $source_name to $destination."
+ return 0
+ else
+ echo " [-] $env_var: Failed to save file from $source_name."
+ return 1
+ fi
+}
+
+# Iterate through the list and download assets
+for env_var in "${ASSETS_ENVS[@]}"; do
+ url="${!env_var}"
+ filename=$(get_target_filename "$env_var")
+ download_and_save_asset "$env_var" "$url" "$filename"
+done
+
+echo "✅ Done."
+echo
diff --git a/explorer/frontend/deploy/scripts/entrypoint.sh b/explorer/frontend/deploy/scripts/entrypoint.sh
new file mode 100755
index 000000000..6abcb1fa6
--- /dev/null
+++ b/explorer/frontend/deploy/scripts/entrypoint.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+
+export_envs_from_preset() {
+ if [ -z "$ENVS_PRESET" ]; then
+ return
+ fi
+
+ if [ "$ENVS_PRESET" = "none" ]; then
+ return
+ fi
+
+ local preset_file="./configs/envs/.env.$ENVS_PRESET"
+
+ if [ ! -f "$preset_file" ]; then
+ return
+ fi
+
+ local blacklist=(
+ "NEXT_PUBLIC_APP_PROTOCOL"
+ "NEXT_PUBLIC_APP_HOST"
+ "NEXT_PUBLIC_APP_PORT"
+ "NEXT_PUBLIC_APP_ENV"
+ "NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL"
+ )
+
+ while IFS='=' read -r name value; do
+ name="${name#"${name%%[![:space:]]*}"}" # Trim leading whitespace
+ if [[ -n $name && $name == "NEXT_PUBLIC_"* && ! "${blacklist[*]}" =~ "$name" ]]; then
+ export "$name"="$value"
+ fi
+ done < <(grep "^[^#;]" "$preset_file")
+}
+
+# If there is a preset, load the environment variables from the its file
+export_envs_from_preset
+
+# Download external assets
+./download_assets.sh ./public/assets/configs
+
+# Check run-time ENVs values
+if [ "$SKIP_ENVS_VALIDATION" != "true" ]; then
+ ./validate_envs.sh
+ if [ $? -ne 0 ]; then
+ exit 1
+ fi
+else
+ echo "😱 Skipping ENVs validation."
+ echo
+fi
+
+# Generate favicons bundle
+./favicon_generator.sh
+if [ $? -ne 0 ]; then
+ echo "👎 Unable to generate favicons bundle."
+else
+ echo "👍 Favicons bundle successfully generated."
+fi
+echo
+
+# Generate OG image
+node --no-warnings ./og_image_generator.js
+
+# Create envs.js file with run-time environment variables for the client app
+./make_envs_script.sh
+
+# Generate sitemap.xml and robots.txt files
+./sitemap_generator.sh
+
+# Print list of enabled features
+node ./feature-reporter.js
+
+echo "Starting Next.js application"
+exec "$@"
diff --git a/explorer/frontend/deploy/scripts/favicon_generator.sh b/explorer/frontend/deploy/scripts/favicon_generator.sh
new file mode 100755
index 000000000..7863bda40
--- /dev/null
+++ b/explorer/frontend/deploy/scripts/favicon_generator.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+master_url="${FAVICON_MASTER_URL:-$NEXT_PUBLIC_NETWORK_ICON}"
+export MASTER_URL="$master_url"
+
+cd ./deploy/tools/favicon-generator
+yarn install --frozen-lockfile
+node "$(pwd)/index.js"
+if [ $? -ne 0 ]; then
+ cd ../../../
+ exit 1
+else
+ cd ../../../
+ favicon_folder="./public/assets/favicon/"
+
+ echo "⏳ Replacing default favicons with freshly generated pack..."
+ if [ -d "$favicon_folder" ]; then
+ rm -r "$favicon_folder"
+ fi
+ mkdir -p "$favicon_folder"
+ cp -r ./deploy/tools/favicon-generator/output/* "$favicon_folder"
+fi
\ No newline at end of file
diff --git a/explorer/frontend/deploy/scripts/make_envs_script.sh b/explorer/frontend/deploy/scripts/make_envs_script.sh
new file mode 100755
index 000000000..b3548cb20
--- /dev/null
+++ b/explorer/frontend/deploy/scripts/make_envs_script.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+echo "🌀 Creating client script with ENV values..."
+
+# Define the output file name
+output_file="${1:-./public/assets/envs.js}"
+
+touch $output_file;
+truncate -s 0 $output_file;
+
+# Check if the .env file exists and load ENVs from it
+if [ -f .env ]; then
+ source .env
+ export $(cut -d= -f1 .env)
+fi
+
+echo "window.__envs = {" >> $output_file;
+
+# Iterate through all environment variables
+for var in $(env | grep '^NEXT_PUBLIC_' | cut -d= -f1); do
+ # Skip variables that start with NEXT_PUBLIC_VERCEL. Vercel injects these
+ # and they can cause runtime errors, particularly when commit messages wrap lines.
+ if [[ $var == NEXT_PUBLIC_VERCEL* ]]; then
+ continue
+ fi
+
+ # Get the value of the variable
+ value="${!var}"
+
+ # Replace double quotes with single quotes
+ value="${value//\"/\'}"
+
+ # Write the variable name and value to the output file
+ echo "${var}: \"${value}\"," >> "$output_file"
+done
+
+echo "}" >> $output_file;
+
+echo "✅ Done."
diff --git a/explorer/frontend/deploy/scripts/og_image_generator.js b/explorer/frontend/deploy/scripts/og_image_generator.js
new file mode 100755
index 000000000..6f607376f
--- /dev/null
+++ b/explorer/frontend/deploy/scripts/og_image_generator.js
@@ -0,0 +1,68 @@
+/* eslint-disable no-console */
+import fs from 'fs';
+import path from 'path';
+
+console.log('🎨 Generating OG image...');
+
+const targetFile = path.resolve(process.cwd(), 'public/static/og_image.png');
+
+function copyPlaceholderImage() {
+ const sourceFile = path.resolve(process.cwd(), 'public/static/og_placeholder.png');
+ fs.copyFileSync(sourceFile, targetFile);
+}
+
+if (process.env.NEXT_PUBLIC_OG_IMAGE_URL) {
+ console.log('⏩ NEXT_PUBLIC_OG_IMAGE_URL is set. Skipping OG image generation...');
+} else if (!process.env.NEXT_PUBLIC_NETWORK_NAME) {
+ console.log('⏩ NEXT_PUBLIC_NETWORK_NAME is not set. Copying placeholder image...');
+ copyPlaceholderImage();
+} else if (!process.env.NEXT_PUBLIC_NETWORK_LOGO && !process.env.NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG) {
+ console.log('⏩ Neither NEXT_PUBLIC_NETWORK_LOGO nor NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG is set. Copying placeholder image...');
+ copyPlaceholderImage();
+} else {
+ try {
+ const bannerConfig = JSON.parse(process.env.NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG?.replaceAll('\'', '"') || '{}');
+ const data = {
+ title: `${ process.env.NEXT_PUBLIC_NETWORK_NAME } explorer`,
+ logo_url: process.env.NEXT_PUBLIC_NETWORK_LOGO_DARK ?? process.env.NEXT_PUBLIC_NETWORK_LOGO,
+ background: bannerConfig.background?.[0],
+ title_color: bannerConfig.text_color?.[0],
+ invert_logo: !process.env.NEXT_PUBLIC_NETWORK_LOGO_DARK,
+ app_url: process.env.NEXT_PUBLIC_APP_HOST,
+ };
+
+ console.log('⏳ Making request to OG image generator service...');
+
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), 30_000);
+
+ const response = await fetch('https://bigs.services.blockscout.com/generate/og', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(data),
+ signal: controller.signal,
+ });
+
+ clearTimeout(timeoutId);
+
+ if (response.ok) {
+ console.log('⬇️ Downloading the image...');
+ const buffer = await response.arrayBuffer();
+ const imageBuffer = Buffer.from(buffer);
+ fs.writeFileSync(targetFile, imageBuffer);
+ } else {
+ const payload = response.headers.get('Content-type')?.includes('application/json') ? await response.json() : await response.text();
+ console.error('🛑 Failed to generate OG image. Response:', payload);
+ console.log('Copying placeholder image...');
+ copyPlaceholderImage();
+ }
+ } catch (error) {
+ console.error('🛑 Failed to generate OG image. Error:', error?.message);
+ console.log('Copying placeholder image...');
+ copyPlaceholderImage();
+ }
+}
+
+console.log('✅ Done.');
diff --git a/explorer/frontend/deploy/scripts/sitemap_generator.sh b/explorer/frontend/deploy/scripts/sitemap_generator.sh
new file mode 100644
index 000000000..fbeb89b51
--- /dev/null
+++ b/explorer/frontend/deploy/scripts/sitemap_generator.sh
@@ -0,0 +1,2 @@
+cd ./deploy/tools/sitemap-generator
+yarn next-sitemap
\ No newline at end of file
diff --git a/explorer/frontend/deploy/scripts/validate_envs.sh b/explorer/frontend/deploy/scripts/validate_envs.sh
new file mode 100755
index 000000000..55211d1c5
--- /dev/null
+++ b/explorer/frontend/deploy/scripts/validate_envs.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# Check if the .env file exists
+if [ -f .env ]; then
+ # Load the environment variables from .env
+ source .env
+fi
+
+# Check run-time ENVs values integrity
+node "$(dirname "$0")/envs-validator.js" "$input"
+if [ $? != 0 ]; then
+ exit 1
+fi
\ No newline at end of file
diff --git a/explorer/frontend/deploy/tools/affected-tests/.gitignore b/explorer/frontend/deploy/tools/affected-tests/.gitignore
new file mode 100644
index 000000000..30bc16279
--- /dev/null
+++ b/explorer/frontend/deploy/tools/affected-tests/.gitignore
@@ -0,0 +1 @@
+/node_modules
\ No newline at end of file
diff --git a/explorer/frontend/deploy/tools/affected-tests/index.js b/explorer/frontend/deploy/tools/affected-tests/index.js
new file mode 100644
index 000000000..f2fc450eb
--- /dev/null
+++ b/explorer/frontend/deploy/tools/affected-tests/index.js
@@ -0,0 +1,208 @@
+/* eslint-disable no-console */
+const { execSync } = require('child_process');
+const dependencyTree = require('dependency-tree');
+const fs = require('fs');
+const path = require('path');
+
+const ROOT_DIR = path.resolve(__dirname, '../../../');
+
+const TARGET_FILE = path.resolve(ROOT_DIR, './playwright/affected-tests.txt');
+
+const NON_EXISTENT_DEPS = [];
+
+const DIRECTORIES_WITH_TESTS = [
+ path.resolve(ROOT_DIR, './ui'),
+];
+const VISITED = {};
+
+function getAllPwFilesInDirectory(directory) {
+ const files = fs.readdirSync(directory, { recursive: true });
+ return files
+ .filter((file) => file.endsWith('.pw.tsx'))
+ .map((file) => path.join(directory, file));
+}
+
+function getFileDeps(filename, changedNpmModules) {
+ return dependencyTree.toList({
+ filename,
+ directory: ROOT_DIR,
+ filter: (path) => {
+ if (path.indexOf('node_modules') === -1) {
+ return true;
+ }
+
+ if (changedNpmModules.some((module) => path.startsWith(module))) {
+ return true;
+ }
+
+ return false;
+ },
+ tsConfig: path.resolve(ROOT_DIR, './tsconfig.json'),
+ nonExistent: NON_EXISTENT_DEPS,
+ visited: VISITED,
+ });
+}
+
+async function getChangedFiles() {
+ const command = process.env.CI ?
+ `git diff --name-only origin/${ process.env.GITHUB_BASE_REF } ${ process.env.GITHUB_SHA } -- ${ ROOT_DIR }` :
+ `git diff --name-only main $(git branch --show-current) -- ${ ROOT_DIR }`;
+
+ console.log('Executing command: ', command);
+ const files = execSync(command)
+ .toString()
+ .trim()
+ .split('\n')
+ .filter(Boolean);
+
+ return files.map((file) => path.join(ROOT_DIR, file));
+}
+
+function checkChangesInChakraTheme(changedFiles) {
+ const themeDir = path.resolve(ROOT_DIR, './theme');
+ return changedFiles.some((file) => file.startsWith(themeDir));
+}
+
+function checkChangesInSvgSprite(changedFiles) {
+ const iconDir = path.resolve(ROOT_DIR, './icons');
+ const areIconsChanged = changedFiles.some((file) => file.startsWith(iconDir));
+
+ if (!areIconsChanged) {
+ return false;
+ }
+
+ const svgNamesFile = path.resolve(ROOT_DIR, './public/icons/name.d.ts');
+ const areSvgNamesChanged = changedFiles.some((file) => file === svgNamesFile);
+
+ if (!areSvgNamesChanged) {
+ // If only the icons have changed and not the names in the SVG file, we will need to run all tests.
+ // This is because we cannot correctly identify the test files that depend on these changes.
+ return true;
+ }
+
+ // If the icon names have changed, then there should be changes in the components that use them.
+ // Otherwise, typescript would complain about that.
+ return false;
+}
+
+function createTargetFile(content) {
+ fs.writeFileSync(TARGET_FILE, content);
+}
+
+function getPackageJsonUpdatedProps(packageJsonFile) {
+ const command = process.env.CI ?
+ `git diff --unified=0 origin/${ process.env.GITHUB_BASE_REF } ${ process.env.GITHUB_SHA } -- ${ packageJsonFile }` :
+ `git diff --unified=0 main $(git branch --show-current) -- ${ packageJsonFile }`;
+
+ console.log('Executing command: ', command);
+ const changedLines = execSync(command)
+ .toString()
+ .trim()
+ .split('\n')
+ .filter(Boolean)
+ .filter((line) => line.startsWith('+ ') || line.startsWith('- '));
+
+ const changedProps = [ ...new Set(
+ changedLines
+ .map((line) => line.replaceAll(' ', '').replaceAll('+', '').replaceAll('-', ''))
+ .map((line) => line.split(':')[0].replaceAll('"', '')),
+ ) ];
+
+ return changedProps;
+}
+
+function getUpdatedNpmModules(changedFiles) {
+ const packageJsonFile = path.resolve(ROOT_DIR, './package.json');
+
+ if (!changedFiles.includes(packageJsonFile)) {
+ return [];
+ }
+
+ try {
+ const packageJsonContent = JSON.parse(fs.readFileSync(packageJsonFile, 'utf-8'));
+ const usedNpmModules = [
+ ...Object.keys(packageJsonContent.dependencies || {}),
+ ...Object.keys(packageJsonContent.devDependencies || {}),
+ ];
+ const updatedProps = getPackageJsonUpdatedProps(packageJsonFile);
+
+ return updatedProps.filter((prop) => usedNpmModules.includes(prop));
+ } catch (error) {}
+}
+
+async function run() {
+ // NOTES:
+ // - The absence of TARGET_FILE implies that all tests should be run.
+ // - The empty TARGET_FILE implies that no tests should be run.
+
+ const start = Date.now();
+
+ fs.unlink(TARGET_FILE, () => {});
+
+ const changedFiles = await getChangedFiles();
+
+ if (!changedFiles.length) {
+ createTargetFile('');
+ console.log('No changed files found. Exiting...');
+ return;
+ }
+
+ console.log('Changed files in the branch: ', changedFiles);
+
+ if (checkChangesInChakraTheme(changedFiles)) {
+ console.log('Changes in Chakra theme detected. It is advisable to run all test suites. Exiting...');
+ return;
+ }
+
+ if (checkChangesInSvgSprite(changedFiles)) {
+ console.log('There are some changes in the SVG sprite that cannot be linked to a specific component. It is advisable to run all test suites. Exiting...');
+ return;
+ }
+
+ let changedNpmModules = getUpdatedNpmModules(changedFiles);
+
+ if (!changedNpmModules) {
+ console.log('Some error occurred while detecting changed NPM modules. It is advisable to run all test suites. Exiting...');
+ return;
+ }
+
+ console.log('Changed NPM modules in the branch: ', changedNpmModules);
+
+ changedNpmModules = [
+ ...changedNpmModules,
+ ...changedNpmModules.map((module) => `@types/${ module }`), // there are some deps that are resolved to .d.ts files
+ ].map((module) => path.resolve(ROOT_DIR, `./node_modules/${ module }`));
+
+ const allTestFiles = DIRECTORIES_WITH_TESTS.reduce((acc, dir) => {
+ return acc.concat(getAllPwFilesInDirectory(dir));
+ }, []);
+
+ const isDepChanged = (dep) => changedFiles.includes(dep) || changedNpmModules.some((module) => dep.startsWith(module));
+
+ const testFilesToRun = allTestFiles
+ .map((file) => ({ file, deps: getFileDeps(file, changedNpmModules) }))
+ .filter(({ deps }) => deps.some(isDepChanged));
+ const testFileNamesToRun = testFilesToRun.map(({ file }) => path.relative(ROOT_DIR, file));
+
+ if (!testFileNamesToRun.length) {
+ createTargetFile('');
+ console.log('No tests to run. Exiting...');
+ return;
+ }
+
+ createTargetFile(testFileNamesToRun.join('\n'));
+
+ const end = Date.now();
+
+ const testFilesToRunWithFilteredDeps = testFilesToRun.map(({ file, deps }) => ({
+ file,
+ deps: deps.filter(isDepChanged),
+ }));
+
+ console.log('Total time: ', ((end - start) / 1_000).toLocaleString());
+ console.log('Total test to run: ', testFileNamesToRun.length);
+ console.log('Tests to run with changed deps: ', testFilesToRunWithFilteredDeps);
+ console.log('Non existent deps: ', NON_EXISTENT_DEPS);
+}
+
+run();
diff --git a/explorer/frontend/deploy/tools/affected-tests/package.json b/explorer/frontend/deploy/tools/affected-tests/package.json
new file mode 100644
index 000000000..bfba5734f
--- /dev/null
+++ b/explorer/frontend/deploy/tools/affected-tests/package.json
@@ -0,0 +1,10 @@
+{
+ "name": "affected-tests",
+ "version": "1.0.0",
+ "main": "index.js",
+ "author": "Vasilii (tom) Goriunov ",
+ "license": "MIT",
+ "dependencies": {
+ "dependency-tree": "10.0.9"
+ }
+}
diff --git a/explorer/frontend/deploy/tools/affected-tests/yarn.lock b/explorer/frontend/deploy/tools/affected-tests/yarn.lock
new file mode 100644
index 000000000..ebfe2bd8b
--- /dev/null
+++ b/explorer/frontend/deploy/tools/affected-tests/yarn.lock
@@ -0,0 +1,716 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@babel/parser@^7.21.8":
+ version "7.23.9"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.9.tgz#7b903b6149b0f8fa7ad564af646c4c38a77fc44b"
+ integrity sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==
+
+"@dependents/detective-less@^4.1.0":
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/@dependents/detective-less/-/detective-less-4.1.0.tgz#4a979ee7a6a79eb33602862d6a1263e30f98002e"
+ integrity sha512-KrkT6qO5NxqNfy68sBl6CTSoJ4SNDIS5iQArkibhlbGU4LaDukZ3q2HIkh8aUKDio6o4itU4xDR7t82Y2eP1Bg==
+ dependencies:
+ gonzales-pe "^4.3.0"
+ node-source-walk "^6.0.1"
+
+"@nodelib/fs.scandir@2.1.5":
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
+ integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
+ dependencies:
+ "@nodelib/fs.stat" "2.0.5"
+ run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
+ integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
+
+"@nodelib/fs.walk@^1.2.3":
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
+ integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
+ dependencies:
+ "@nodelib/fs.scandir" "2.1.5"
+ fastq "^1.6.0"
+
+"@typescript-eslint/types@5.62.0":
+ version "5.62.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f"
+ integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==
+
+"@typescript-eslint/typescript-estree@^5.59.5":
+ version "5.62.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b"
+ integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==
+ dependencies:
+ "@typescript-eslint/types" "5.62.0"
+ "@typescript-eslint/visitor-keys" "5.62.0"
+ debug "^4.3.4"
+ globby "^11.1.0"
+ is-glob "^4.0.3"
+ semver "^7.3.7"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/visitor-keys@5.62.0":
+ version "5.62.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e"
+ integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==
+ dependencies:
+ "@typescript-eslint/types" "5.62.0"
+ eslint-visitor-keys "^3.3.0"
+
+app-module-path@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5"
+ integrity sha512-gkco+qxENJV+8vFcDiiFhuoSvRXb2a/QPqpSoWhVz829VNJfOTnELbBmPmNKFxf3xdNnw4DWCkzkDaavcX/1YQ==
+
+array-union@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
+ integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+
+ast-module-types@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/ast-module-types/-/ast-module-types-5.0.0.tgz#32b2b05c56067ff38e95df66f11d6afd6c9ba16b"
+ integrity sha512-JvqziE0Wc0rXQfma0HZC/aY7URXHFuZV84fJRtP8u+lhp0JYCNd5wJzVXP45t0PH0Mej3ynlzvdyITYIu0G4LQ==
+
+balanced-match@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+ integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+braces@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
+ integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
+ dependencies:
+ fill-range "^7.1.1"
+
+color-name@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+commander@^10.0.1:
+ version "10.0.1"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
+ integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
+
+debug@^4.3.4:
+ version "4.3.4"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
+ integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
+ dependencies:
+ ms "2.1.2"
+
+dependency-tree@10.0.9:
+ version "10.0.9"
+ resolved "https://registry.yarnpkg.com/dependency-tree/-/dependency-tree-10.0.9.tgz#0c6c0dbeb0c5ec2cf83bf755f30e9cb12e7b4ac7"
+ integrity sha512-dwc59FRIsht+HfnTVM0BCjJaEWxdq2YAvEDy4/Hn6CwS3CBWMtFnL3aZGAkQn3XCYxk/YcTDE4jX2Q7bFTwCjA==
+ dependencies:
+ commander "^10.0.1"
+ filing-cabinet "^4.1.6"
+ precinct "^11.0.5"
+ typescript "^5.0.4"
+
+detective-amd@^5.0.2:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/detective-amd/-/detective-amd-5.0.2.tgz#579900f301c160efe037a6377ec7e937434b2793"
+ integrity sha512-XFd/VEQ76HSpym80zxM68ieB77unNuoMwopU2TFT/ErUk5n4KvUTwW4beafAVUugrjV48l4BmmR0rh2MglBaiA==
+ dependencies:
+ ast-module-types "^5.0.0"
+ escodegen "^2.0.0"
+ get-amd-module-type "^5.0.1"
+ node-source-walk "^6.0.1"
+
+detective-cjs@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/detective-cjs/-/detective-cjs-5.0.1.tgz#836ad51c6de4863efc7c419ec243694f760ff8b2"
+ integrity sha512-6nTvAZtpomyz/2pmEmGX1sXNjaqgMplhQkskq2MLrar0ZAIkHMrDhLXkRiK2mvbu9wSWr0V5/IfiTrZqAQMrmQ==
+ dependencies:
+ ast-module-types "^5.0.0"
+ node-source-walk "^6.0.0"
+
+detective-es6@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/detective-es6/-/detective-es6-4.0.1.tgz#38d5d49a6d966e992ef8f2d9bffcfe861a58a88a"
+ integrity sha512-k3Z5tB4LQ8UVHkuMrFOlvb3GgFWdJ9NqAa2YLUU/jTaWJIm+JJnEh4PsMc+6dfT223Y8ACKOaC0qcj7diIhBKw==
+ dependencies:
+ node-source-walk "^6.0.1"
+
+detective-postcss@^6.1.3:
+ version "6.1.3"
+ resolved "https://registry.yarnpkg.com/detective-postcss/-/detective-postcss-6.1.3.tgz#51a2d4419327ad85d0af071c7054c79fafca7e73"
+ integrity sha512-7BRVvE5pPEvk2ukUWNQ+H2XOq43xENWbH0LcdCE14mwgTBEAMoAx+Fc1rdp76SmyZ4Sp48HlV7VedUnP6GA1Tw==
+ dependencies:
+ is-url "^1.2.4"
+ postcss "^8.4.23"
+ postcss-values-parser "^6.0.2"
+
+detective-sass@^5.0.3:
+ version "5.0.3"
+ resolved "https://registry.yarnpkg.com/detective-sass/-/detective-sass-5.0.3.tgz#63e54bc9b32f4bdbd9d5002308f9592a3d3a508f"
+ integrity sha512-YsYT2WuA8YIafp2RVF5CEfGhhyIVdPzlwQgxSjK+TUm3JoHP+Tcorbk3SfG0cNZ7D7+cYWa0ZBcvOaR0O8+LlA==
+ dependencies:
+ gonzales-pe "^4.3.0"
+ node-source-walk "^6.0.1"
+
+detective-scss@^4.0.3:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/detective-scss/-/detective-scss-4.0.3.tgz#79758baa0158f72bfc4481eb7e21cc3b5f1ea6eb"
+ integrity sha512-VYI6cHcD0fLokwqqPFFtDQhhSnlFWvU614J42eY6G0s8c+MBhi9QAWycLwIOGxlmD8I/XvGSOUV1kIDhJ70ZPg==
+ dependencies:
+ gonzales-pe "^4.3.0"
+ node-source-walk "^6.0.1"
+
+detective-stylus@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/detective-stylus/-/detective-stylus-4.0.0.tgz#ce97b6499becdc291de7b3c11df8c352c1eee46e"
+ integrity sha512-TfPotjhszKLgFBzBhTOxNHDsutIxx9GTWjrL5Wh7Qx/ydxKhwUrlSFeLIn+ZaHPF+h0siVBkAQSuy6CADyTxgQ==
+
+detective-typescript@^11.1.0:
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/detective-typescript/-/detective-typescript-11.1.0.tgz#2deea5364cae1f0d9d3688bc596e662b049438cc"
+ integrity sha512-Mq8egjnW2NSCkzEb/Az15/JnBI/Ryyl6Po0Y+0mABTFvOS6DAyUGRZqz1nyhu4QJmWWe0zaGs/ITIBeWkvCkGw==
+ dependencies:
+ "@typescript-eslint/typescript-estree" "^5.59.5"
+ ast-module-types "^5.0.0"
+ node-source-walk "^6.0.1"
+ typescript "^5.0.4"
+
+dir-glob@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
+ integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
+ dependencies:
+ path-type "^4.0.0"
+
+enhanced-resolve@^5.14.1:
+ version "5.15.0"
+ resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35"
+ integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==
+ dependencies:
+ graceful-fs "^4.2.4"
+ tapable "^2.2.0"
+
+escodegen@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17"
+ integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==
+ dependencies:
+ esprima "^4.0.1"
+ estraverse "^5.2.0"
+ esutils "^2.0.2"
+ optionalDependencies:
+ source-map "~0.6.1"
+
+eslint-visitor-keys@^3.3.0:
+ version "3.4.3"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
+ integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
+
+esprima@^4.0.0, esprima@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
+ integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
+
+estraverse@^5.2.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
+ integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
+
+esutils@^2.0.2:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
+ integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
+
+fast-glob@^3.2.9:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129"
+ integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==
+ dependencies:
+ "@nodelib/fs.stat" "^2.0.2"
+ "@nodelib/fs.walk" "^1.2.3"
+ glob-parent "^5.1.2"
+ merge2 "^1.3.0"
+ micromatch "^4.0.4"
+
+fastq@^1.6.0:
+ version "1.17.0"
+ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.0.tgz#ca5e1a90b5e68f97fc8b61330d5819b82f5fab03"
+ integrity sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==
+ dependencies:
+ reusify "^1.0.4"
+
+filing-cabinet@^4.1.6:
+ version "4.1.6"
+ resolved "https://registry.yarnpkg.com/filing-cabinet/-/filing-cabinet-4.1.6.tgz#8d6d12cf3a84365bbd94e1cbf07d71c113420dd2"
+ integrity sha512-C+HZbuQTER36sKzGtUhrAPAoK6+/PrrUhYDBQEh3kBRdsyEhkLbp1ML8S0+6e6gCUrUlid+XmubxJrhvL2g/Zw==
+ dependencies:
+ app-module-path "^2.2.0"
+ commander "^10.0.1"
+ enhanced-resolve "^5.14.1"
+ is-relative-path "^1.0.2"
+ module-definition "^5.0.1"
+ module-lookup-amd "^8.0.5"
+ resolve "^1.22.3"
+ resolve-dependency-path "^3.0.2"
+ sass-lookup "^5.0.1"
+ stylus-lookup "^5.0.1"
+ tsconfig-paths "^4.2.0"
+ typescript "^5.0.4"
+
+fill-range@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
+ integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+ integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+
+function-bind@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
+ integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
+
+get-amd-module-type@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/get-amd-module-type/-/get-amd-module-type-5.0.1.tgz#bef38ea3674e1aa1bda9c59c8b0da598582f73f2"
+ integrity sha512-jb65zDeHyDjFR1loOVk0HQGM5WNwoGB8aLWy3LKCieMKol0/ProHkhO2X1JxojuN10vbz1qNn09MJ7tNp7qMzw==
+ dependencies:
+ ast-module-types "^5.0.0"
+ node-source-walk "^6.0.1"
+
+get-own-enumerable-property-symbols@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664"
+ integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==
+
+glob-parent@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+ dependencies:
+ is-glob "^4.0.1"
+
+glob@^7.2.3:
+ version "7.2.3"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
+ integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.1.1"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+globby@^11.1.0:
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
+ integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
+ dependencies:
+ array-union "^2.1.0"
+ dir-glob "^3.0.1"
+ fast-glob "^3.2.9"
+ ignore "^5.2.0"
+ merge2 "^1.4.1"
+ slash "^3.0.0"
+
+gonzales-pe@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.3.0.tgz#fe9dec5f3c557eead09ff868c65826be54d067b3"
+ integrity sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==
+ dependencies:
+ minimist "^1.2.5"
+
+graceful-fs@^4.2.4:
+ version "4.2.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
+ integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
+
+hasown@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c"
+ integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==
+ dependencies:
+ function-bind "^1.1.2"
+
+ignore@^5.2.0:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef"
+ integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+is-core-module@^2.13.0:
+ version "2.13.1"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384"
+ integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==
+ dependencies:
+ hasown "^2.0.0"
+
+is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+ integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-glob@^4.0.1, is-glob@^4.0.3:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+is-obj@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
+ integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==
+
+is-regexp@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
+ integrity sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==
+
+is-relative-path@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-relative-path/-/is-relative-path-1.0.2.tgz#091b46a0d67c1ed0fe85f1f8cfdde006bb251d46"
+ integrity sha512-i1h+y50g+0hRbBD+dbnInl3JlJ702aar58snAeX+MxBAPvzXGej7sYoPMhlnykabt0ZzCJNBEyzMlekuQZN7fA==
+
+is-url-superb@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/is-url-superb/-/is-url-superb-4.0.0.tgz#b54d1d2499bb16792748ac967aa3ecb41a33a8c2"
+ integrity sha512-GI+WjezhPPcbM+tqE9LnmsY5qqjwHzTvjJ36wxYX5ujNXefSUJ/T17r5bqDV8yLhcgB59KTPNOc9O9cmHTPWsA==
+
+is-url@^1.2.4:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52"
+ integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==
+
+json5@^2.2.2:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
+ integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
+
+lru-cache@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
+ integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
+ dependencies:
+ yallist "^4.0.0"
+
+merge2@^1.3.0, merge2@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
+ integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+
+micromatch@^4.0.4:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
+ integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
+ dependencies:
+ braces "^3.0.3"
+ picomatch "^2.3.1"
+
+minimatch@^3.1.1:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
+ integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
+ dependencies:
+ brace-expansion "^1.1.7"
+
+minimist@^1.2.5, minimist@^1.2.6:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
+ integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+
+module-definition@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/module-definition/-/module-definition-5.0.1.tgz#62d1194e5d5ea6176b7dc7730f818f466aefa32f"
+ integrity sha512-kvw3B4G19IXk+BOXnYq/D/VeO9qfHaapMeuS7w7sNUqmGaA6hywdFHMi+VWeR9wUScXM7XjoryTffCZ5B0/8IA==
+ dependencies:
+ ast-module-types "^5.0.0"
+ node-source-walk "^6.0.1"
+
+module-lookup-amd@^8.0.5:
+ version "8.0.5"
+ resolved "https://registry.yarnpkg.com/module-lookup-amd/-/module-lookup-amd-8.0.5.tgz#aaeea41979105b49339380ca3f7d573db78c32a5"
+ integrity sha512-vc3rYLjDo5Frjox8NZpiyLXsNWJ5BWshztc/5KSOMzpg9k5cHH652YsJ7VKKmtM4SvaxuE9RkrYGhiSjH3Ehow==
+ dependencies:
+ commander "^10.0.1"
+ glob "^7.2.3"
+ requirejs "^2.3.6"
+ requirejs-config-file "^4.0.0"
+
+ms@2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+ integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+nanoid@^3.3.7:
+ version "3.3.8"
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf"
+ integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==
+
+node-source-walk@^6.0.0, node-source-walk@^6.0.1, node-source-walk@^6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/node-source-walk/-/node-source-walk-6.0.2.tgz#ba81bc4bc0f6f05559b084bea10be84c3f87f211"
+ integrity sha512-jn9vOIK/nfqoFCcpK89/VCVaLg1IHE6UVfDOzvqmANaJ/rWCTEdH8RZ1V278nv2jr36BJdyQXIAavBLXpzdlag==
+ dependencies:
+ "@babel/parser" "^7.21.8"
+
+once@^1.3.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
+ dependencies:
+ wrappy "1"
+
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+ integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
+
+path-parse@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+
+path-type@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
+ integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+
+picocolors@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
+ integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
+
+picomatch@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+postcss-values-parser@^6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-6.0.2.tgz#636edc5b86c953896f1bb0d7a7a6615df00fb76f"
+ integrity sha512-YLJpK0N1brcNJrs9WatuJFtHaV9q5aAOj+S4DI5S7jgHlRfm0PIbDCAFRYMQD5SHq7Fy6xsDhyutgS0QOAs0qw==
+ dependencies:
+ color-name "^1.1.4"
+ is-url-superb "^4.0.0"
+ quote-unquote "^1.0.0"
+
+postcss@^8.4.23:
+ version "8.4.33"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.33.tgz#1378e859c9f69bf6f638b990a0212f43e2aaa742"
+ integrity sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==
+ dependencies:
+ nanoid "^3.3.7"
+ picocolors "^1.0.0"
+ source-map-js "^1.0.2"
+
+precinct@^11.0.5:
+ version "11.0.5"
+ resolved "https://registry.yarnpkg.com/precinct/-/precinct-11.0.5.tgz#3e15b3486670806f18addb54b8533e23596399ff"
+ integrity sha512-oHSWLC8cL/0znFhvln26D14KfCQFFn4KOLSw6hmLhd+LQ2SKt9Ljm89but76Pc7flM9Ty1TnXyrA2u16MfRV3w==
+ dependencies:
+ "@dependents/detective-less" "^4.1.0"
+ commander "^10.0.1"
+ detective-amd "^5.0.2"
+ detective-cjs "^5.0.1"
+ detective-es6 "^4.0.1"
+ detective-postcss "^6.1.3"
+ detective-sass "^5.0.3"
+ detective-scss "^4.0.3"
+ detective-stylus "^4.0.0"
+ detective-typescript "^11.1.0"
+ module-definition "^5.0.1"
+ node-source-walk "^6.0.2"
+
+queue-microtask@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
+ integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+
+quote-unquote@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/quote-unquote/-/quote-unquote-1.0.0.tgz#67a9a77148effeaf81a4d428404a710baaac8a0b"
+ integrity sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg==
+
+requirejs-config-file@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/requirejs-config-file/-/requirejs-config-file-4.0.0.tgz#4244da5dd1f59874038cc1091d078d620abb6ebc"
+ integrity sha512-jnIre8cbWOyvr8a5F2KuqBnY+SDA4NXr/hzEZJG79Mxm2WiFQz2dzhC8ibtPJS7zkmBEl1mxSwp5HhC1W4qpxw==
+ dependencies:
+ esprima "^4.0.0"
+ stringify-object "^3.2.1"
+
+requirejs@^2.3.6:
+ version "2.3.7"
+ resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.7.tgz#0b22032e51a967900e0ae9f32762c23a87036bd0"
+ integrity "sha1-CyIDLlGpZ5AOCunzJ2LCOocDa9A= sha512-DouTG8T1WanGok6Qjg2SXuCMzszOo0eHeH9hDZ5Y4x8Je+9JB38HdTLT4/VA8OaUhBa0JPVHJ0pyBkM1z+pDsw=="
+
+resolve-dependency-path@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/resolve-dependency-path/-/resolve-dependency-path-3.0.2.tgz#012816717bcbe8b846835da11af9d2beb5acef50"
+ integrity sha512-Tz7zfjhLfsvR39ADOSk9us4421J/1ztVBo4rWUkF38hgHK5m0OCZ3NxFVpqHRkjctnwVa15igEUHFJp8MCS7vA==
+
+resolve@^1.22.3:
+ version "1.22.8"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
+ integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
+ dependencies:
+ is-core-module "^2.13.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+reusify@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
+ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
+run-parallel@^1.1.9:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
+ integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+ dependencies:
+ queue-microtask "^1.2.2"
+
+sass-lookup@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/sass-lookup/-/sass-lookup-5.0.1.tgz#1f01d7ff21e09d8c9dcf8d05b3fca28f2f96e6ed"
+ integrity sha512-t0X5PaizPc2H4+rCwszAqHZRtr4bugo4pgiCvrBFvIX0XFxnr29g77LJcpyj9A0DcKf7gXMLcgvRjsonYI6x4g==
+ dependencies:
+ commander "^10.0.1"
+
+semver@^7.3.7:
+ version "7.5.4"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
+ integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
+ dependencies:
+ lru-cache "^6.0.0"
+
+slash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
+ integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
+
+source-map-js@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
+ integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
+
+source-map@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+stringify-object@^3.2.1:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629"
+ integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==
+ dependencies:
+ get-own-enumerable-property-symbols "^3.0.0"
+ is-obj "^1.0.1"
+ is-regexp "^1.0.0"
+
+strip-bom@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
+ integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==
+
+stylus-lookup@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/stylus-lookup/-/stylus-lookup-5.0.1.tgz#3c4d116c3b1e8e1a8169c0d9cd20e608595560f4"
+ integrity sha512-tLtJEd5AGvnVy4f9UHQMw4bkJJtaAcmo54N+ovQBjDY3DuWyK9Eltxzr5+KG0q4ew6v2EHyuWWNnHeiw/Eo7rQ==
+ dependencies:
+ commander "^10.0.1"
+
+supports-preserve-symlinks-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
+ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
+tapable@^2.2.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
+ integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+tsconfig-paths@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c"
+ integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==
+ dependencies:
+ json5 "^2.2.2"
+ minimist "^1.2.6"
+ strip-bom "^3.0.0"
+
+tslib@^1.8.1:
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
+ integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
+
+tsutils@^3.21.0:
+ version "3.21.0"
+ resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
+ integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
+ dependencies:
+ tslib "^1.8.1"
+
+typescript@^5.0.4:
+ version "5.3.3"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
+ integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+ integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
+
+yallist@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
+ integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
diff --git a/explorer/frontend/deploy/tools/envs-validator/.gitignore b/explorer/frontend/deploy/tools/envs-validator/.gitignore
new file mode 100644
index 000000000..caba20fba
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/.gitignore
@@ -0,0 +1,6 @@
+/node_modules
+/public
+.env
+.env.registry
+.env.secrets
+index.js
\ No newline at end of file
diff --git a/explorer/frontend/deploy/tools/envs-validator/index.ts b/explorer/frontend/deploy/tools/envs-validator/index.ts
new file mode 100644
index 000000000..98769d1fe
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/index.ts
@@ -0,0 +1,201 @@
+/* eslint-disable no-console */
+import fs from 'fs';
+import path from 'path';
+import type { ValidationError } from 'yup';
+
+import { buildExternalAssetFilePath } from '../../../configs/app/utils';
+import schema from './schema';
+
+const silent = process.argv.includes('--silent');
+
+run();
+
+async function run() {
+ !silent && console.log();
+ try {
+ const appEnvs = Object.entries(process.env)
+ .filter(([ key ]) => key.startsWith('NEXT_PUBLIC_'))
+ .reduce((result, [ key, value ]) => {
+ result[key] = value || '';
+ return result;
+ }, {} as Record);
+
+ printDeprecationWarning(appEnvs);
+ await checkPlaceholdersCongruity(appEnvs);
+ checkDeprecatedEnvs(appEnvs);
+ await validateEnvs(appEnvs);
+
+ } catch (error) {
+ process.exit(1);
+ }
+}
+
+async function validateEnvs(appEnvs: Record) {
+ !silent && console.log(`🌀 Validating ENV variables values...`);
+
+ try {
+ // replace ENVs with external JSON files content
+ const envsWithJsonConfig = [
+ 'NEXT_PUBLIC_FEATURED_NETWORKS',
+ 'NEXT_PUBLIC_MARKETPLACE_CONFIG_URL',
+ 'NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL',
+ 'NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL',
+ 'NEXT_PUBLIC_MARKETPLACE_GRAPH_LINKS_URL',
+ 'NEXT_PUBLIC_FOOTER_LINKS',
+ ];
+
+ for await (const envName of envsWithJsonConfig) {
+ if (appEnvs[envName]) {
+ appEnvs[envName] = await getExternalJsonContent(envName) || '[]';
+ }
+ }
+
+ await schema.validate(appEnvs, { stripUnknown: false, abortEarly: false });
+ !silent && console.log('👍 All good!');
+ } catch (_error) {
+ if (typeof _error === 'object' && _error !== null && 'errors' in _error) {
+ console.log('🚨 ENVs validation failed with the following errors:');
+ (_error as ValidationError).errors.forEach((error) => {
+ console.log(' ', error);
+ });
+ } else {
+ console.log('🚨 Unexpected error occurred during validation.');
+ console.error(_error);
+ }
+
+ throw _error;
+ }
+
+ !silent && console.log();
+}
+
+async function getExternalJsonContent(envName: string): Promise {
+ return new Promise((resolve, reject) => {
+ const fileName = `./public${ buildExternalAssetFilePath(envName, 'https://foo.bar/baz.json') }`;
+
+ fs.readFile(path.resolve(__dirname, fileName), 'utf8', (err, data) => {
+ if (err) {
+ console.log(`🚨 Unable to read file: ${ fileName }`);
+ reject(err);
+ return;
+ }
+
+ resolve(data);
+ });
+ });
+}
+
+async function checkPlaceholdersCongruity(envsMap: Record) {
+ try {
+ !silent && console.log(`🌀 Checking environment variables and their placeholders congruity...`);
+
+ const runTimeEnvs = await getEnvsPlaceholders(path.resolve(__dirname, '.env.registry'));
+ const buildTimeEnvs = await getEnvsPlaceholders(path.resolve(__dirname, '.env'));
+ const envs = Object.keys(envsMap).filter((env) => !buildTimeEnvs.includes(env));
+
+ const inconsistencies: Array = [];
+ for (const env of envs) {
+ const hasPlaceholder = runTimeEnvs.includes(env);
+ if (!hasPlaceholder) {
+ inconsistencies.push(env);
+ }
+ }
+
+ if (inconsistencies.length > 0) {
+ console.log('🚸 For the following environment variables placeholders were not generated at build-time:');
+ inconsistencies.forEach((env) => {
+ console.log(` ${ env }`);
+ });
+ console.log(` They are either deprecated or running the app with them may lead to unexpected behavior.
+ Please check the documentation for more details - https://github.com/blockscout/frontend/blob/main/docs/ENVS.md
+ `);
+ throw new Error();
+ }
+
+ !silent && console.log('👍 All good!\n');
+ } catch (error) {
+ console.log('🚨 Congruity check failed.\n');
+ throw error;
+ }
+}
+
+function getEnvsPlaceholders(filePath: string): Promise> {
+ return new Promise((resolve, reject) => {
+ fs.readFile(filePath, 'utf8', (err, data) => {
+ if (err) {
+ console.log(`🚨 Unable to read placeholders file.`);
+ reject(err);
+ return;
+ }
+
+ const lines = data.split('\n');
+ const variables = lines.map(line => {
+ const variable = line.split('=')[0];
+ return variable.trim();
+ });
+
+ resolve(variables.filter(Boolean));
+ });
+ });
+}
+
+function printDeprecationWarning(envsMap: Record) {
+ if (envsMap.NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY && envsMap.NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY) {
+ // eslint-disable-next-line max-len
+ console.warn('❗ The NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY variable is now deprecated and will be removed in the next release. Please migrate to the NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY variable.');
+ }
+
+ if (
+ (envsMap.NEXT_PUBLIC_SENTRY_DSN || envsMap.SENTRY_CSP_REPORT_URI || envsMap.NEXT_PUBLIC_SENTRY_ENABLE_TRACING) &&
+ envsMap.NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN
+ ) {
+ // eslint-disable-next-line max-len
+ console.warn('❗ The Sentry monitoring is now deprecated and will be removed in the next release. Please migrate to the Rollbar error monitoring.');
+ }
+
+ if (
+ envsMap.NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME ||
+ envsMap.NEXT_PUBLIC_ROLLUP_L1_BASE_URL
+ ) {
+ // eslint-disable-next-line max-len
+ console.warn('❗ The NEXT_PUBLIC_ROLLUP_L1_BASE_URL and NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME variables are now deprecated and will be removed in the next release. Please migrate to the NEXT_PUBLIC_ROLLUP_PARENT_CHAIN variable.');
+ }
+
+ if (
+ envsMap.NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR ||
+ envsMap.NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND
+ ) {
+ // eslint-disable-next-line max-len
+ console.warn('❗ The NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR and NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND variables are now deprecated and will be removed in the next release. Please migrate to the NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG variable.');
+ }
+
+ if (
+ envsMap.NEXT_PUBLIC_AUTH0_CLIENT_ID ||
+ envsMap.NEXT_PUBLIC_AUTH_URL ||
+ envsMap.NEXT_PUBLIC_LOGOUT_URL
+ ) {
+ // eslint-disable-next-line max-len
+ console.warn('❗ The NEXT_PUBLIC_AUTH0_CLIENT_ID, NEXT_PUBLIC_AUTH_URL and NEXT_PUBLIC_LOGOUT_URL variables are now deprecated and will be removed in the next release.');
+ }
+}
+
+function checkDeprecatedEnvs(envsMap: Record) {
+ !silent && console.log(`🌀 Checking deprecated environment variables...`);
+
+ if (!envsMap.NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY && envsMap.NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY) {
+ // eslint-disable-next-line max-len
+ console.log('🚨 The NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY variable is no longer supported. Please pass NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY or remove it completely.');
+ throw new Error();
+ }
+
+ if (
+ (envsMap.NEXT_PUBLIC_SENTRY_DSN || envsMap.SENTRY_CSP_REPORT_URI || envsMap.NEXT_PUBLIC_SENTRY_ENABLE_TRACING) &&
+ !envsMap.NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN
+ ) {
+ // eslint-disable-next-line max-len
+ console.log('🚨 The Sentry error monitoring is no longer supported. Please migrate to the Rollbar error monitoring.');
+ throw new Error();
+ }
+
+ !silent && console.log('👍 All good!\n');
+}
diff --git a/explorer/frontend/deploy/tools/envs-validator/package.json b/explorer/frontend/deploy/tools/envs-validator/package.json
new file mode 100644
index 000000000..1cc180395
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "envs-validator",
+ "version": "1.0.0",
+ "main": "index.js",
+ "license": "MIT",
+ "scripts": {
+ "build": "yarn webpack-cli -c ./webpack.config.js",
+ "validate": "node ./index.js",
+ "test": "./test.sh"
+ },
+ "dependencies": {
+ "ts-loader": "^9.4.4",
+ "webpack": "^5.88.2",
+ "webpack-cli": "^5.1.4",
+ "yup": "^1.2.0"
+ },
+ "devDependencies": {
+ "dotenv-cli": "^7.2.1",
+ "tsconfig-paths-webpack-plugin": "^4.1.0"
+ }
+}
diff --git a/explorer/frontend/deploy/tools/envs-validator/schema.ts b/explorer/frontend/deploy/tools/envs-validator/schema.ts
new file mode 100644
index 000000000..ebb6517b5
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/schema.ts
@@ -0,0 +1,1083 @@
+/* eslint-disable max-len */
+declare module 'yup' {
+ interface StringSchema {
+ // Yup's URL validator is not perfect so we made our own
+ // https://github.com/jquense/yup/pull/1859
+ url(): never;
+ }
+}
+
+import * as yup from 'yup';
+
+import type { AdButlerConfig } from '../../../types/client/adButlerConfig';
+import type { AddressProfileAPIConfig } from '../../../types/client/addressProfileAPIConfig';
+import { SUPPORTED_AD_TEXT_PROVIDERS, SUPPORTED_AD_BANNER_PROVIDERS, SUPPORTED_AD_BANNER_ADDITIONAL_PROVIDERS } from '../../../types/client/adProviders';
+import type { AdTextProviders, AdBannerProviders, AdBannerAdditionalProviders } from '../../../types/client/adProviders';
+import { SMART_CONTRACT_EXTRA_VERIFICATION_METHODS, SMART_CONTRACT_LANGUAGE_FILTERS, type ContractCodeIde, type SmartContractVerificationMethodExtra } from '../../../types/client/contract';
+import type { DeFiDropdownItem } from '../../../types/client/deFiDropdown';
+import type { GasRefuelProviderConfig } from '../../../types/client/gasRefuelProviderConfig';
+import { GAS_UNITS } from '../../../types/client/gasTracker';
+import type { GasUnit } from '../../../types/client/gasTracker';
+import type { MarketplaceAppOverview, MarketplaceAppSecurityReportRaw, MarketplaceAppSecurityReport } from '../../../types/client/marketplace';
+import type { MultichainProviderConfig } from '../../../types/client/multichainProviderConfig';
+import { NAVIGATION_LINK_IDS } from '../../../types/client/navigation';
+import type { NavItemExternal, NavigationLinkId, NavigationLayout } from '../../../types/client/navigation';
+import { ROLLUP_TYPES } from '../../../types/client/rollup';
+import type { BridgedTokenChain, TokenBridge } from '../../../types/client/token';
+import { PROVIDERS as TX_INTERPRETATION_PROVIDERS } from '../../../types/client/txInterpretation';
+import { VALIDATORS_CHAIN_TYPE } from '../../../types/client/validators';
+import type { ValidatorsChainType } from '../../../types/client/validators';
+import type { WalletType } from '../../../types/client/wallets';
+import { SUPPORTED_WALLETS } from '../../../types/client/wallets';
+import type { CustomLink, CustomLinksGroup } from '../../../types/footerLinks';
+import { CHAIN_INDICATOR_IDS, HOME_STATS_WIDGET_IDS } from '../../../types/homepage';
+import type { ChainIndicatorId, HeroBannerButtonState, HeroBannerConfig, HomeStatsWidgetId } from '../../../types/homepage';
+import { type NetworkVerificationTypeEnvs, type NetworkExplorer, type FeaturedNetwork, NETWORK_GROUPS } from '../../../types/networks';
+import { COLOR_THEME_IDS } from '../../../types/settings';
+import type { FontFamily } from '../../../types/ui';
+import type { AddressFormat, AddressViewId } from '../../../types/views/address';
+import { ADDRESS_FORMATS, ADDRESS_VIEWS_IDS, IDENTICON_TYPES } from '../../../types/views/address';
+import { BLOCK_FIELDS_IDS } from '../../../types/views/block';
+import type { BlockFieldId } from '../../../types/views/block';
+import type { NftMarketplaceItem } from '../../../types/views/nft';
+import type { TxAdditionalFieldsId, TxFieldsId } from '../../../types/views/tx';
+import { TX_ADDITIONAL_FIELDS_IDS, TX_FIELDS_IDS } from '../../../types/views/tx';
+import type { VerifiedContractsFilter } from '../../../types/api/contracts';
+import type { TxExternalTxsConfig } from '../../../types/client/externalTxsConfig';
+
+import { replaceQuotes } from '../../../configs/app/utils';
+import * as regexp from '../../../toolkit/utils/regexp';
+import type { IconName } from '../../../ui/shared/IconSvg';
+
+const protocols = [ 'http', 'https' ];
+
+const urlTest: yup.TestConfig = {
+ name: 'url',
+ test: (value: unknown) => {
+ if (!value) {
+ return true;
+ }
+
+ try {
+ if (typeof value === 'string') {
+ new URL(value);
+ return true;
+ }
+ } catch (error) {}
+
+ return false;
+ },
+ message: '${path} is not a valid URL',
+ exclusive: true,
+};
+
+const getYupValidationErrorMessage = (error: unknown) =>
+ typeof error === 'object' &&
+ error !== null &&
+ 'errors' in error &&
+ Array.isArray(error.errors) ?
+ error.errors.join(', ') :
+ '';
+
+const marketplaceAppSchema: yup.ObjectSchema = yup
+ .object({
+ id: yup.string().required(),
+ external: yup.boolean(),
+ title: yup.string().required(),
+ logo: yup.string().test(urlTest).required(),
+ logoDarkMode: yup.string().test(urlTest),
+ shortDescription: yup.string().required(),
+ categories: yup.array().of(yup.string().required()).required(),
+ url: yup.string().test(urlTest).required(),
+ author: yup.string().required(),
+ description: yup.string().required(),
+ site: yup.string().test(urlTest),
+ twitter: yup.string().test(urlTest),
+ telegram: yup.string().test(urlTest),
+ github: yup.lazy(value =>
+ Array.isArray(value) ?
+ yup.array().of(yup.string().required().test(urlTest)) :
+ yup.string().test(urlTest),
+ ),
+ discord: yup.string().test(urlTest),
+ internalWallet: yup.boolean(),
+ priority: yup.number(),
+ });
+
+const issueSeverityDistributionSchema: yup.ObjectSchema = yup
+ .object({
+ critical: yup.number().required(),
+ gas: yup.number().required(),
+ high: yup.number().required(),
+ informational: yup.number().required(),
+ low: yup.number().required(),
+ medium: yup.number().required(),
+ });
+
+const solidityscanReportSchema: yup.ObjectSchema = yup
+ .object({
+ contractname: yup.string().required(),
+ scan_status: yup.string().required(),
+ scan_summary: yup
+ .object({
+ issue_severity_distribution: issueSeverityDistributionSchema.required(),
+ lines_analyzed_count: yup.number().required(),
+ scan_time_taken: yup.number().required(),
+ score: yup.string().required(),
+ score_v2: yup.string().required(),
+ threat_score: yup.string().required(),
+ })
+ .required(),
+ scanner_reference_url: yup.string().test(urlTest).required(),
+ });
+
+const contractDataSchema: yup.ObjectSchema = yup
+ .object({
+ address: yup.string().required(),
+ isVerified: yup.boolean().required(),
+ solidityScanReport: solidityscanReportSchema.nullable().notRequired(),
+ });
+
+const chainsDataSchema = yup.lazy((objValue) => {
+ let schema = yup.object();
+ Object.keys(objValue).forEach((key) => {
+ schema = schema.shape({
+ [key]: yup.object({
+ overallInfo: yup.object({
+ verifiedNumber: yup.number().required(),
+ totalContractsNumber: yup.number().required(),
+ solidityScanContractsNumber: yup.number().required(),
+ securityScore: yup.number().required(),
+ issueSeverityDistribution: issueSeverityDistributionSchema.required(),
+ }).required(),
+ contractsData: yup.array().of(contractDataSchema).required(),
+ }),
+ });
+ });
+ return schema;
+});
+
+const securityReportSchema: yup.ObjectSchema = yup
+ .object({
+ appName: yup.string().required(),
+ chainsData: chainsDataSchema,
+ });
+
+const marketplaceSchema = yup
+ .object()
+ .shape({
+ NEXT_PUBLIC_MARKETPLACE_ENABLED: yup.boolean(),
+ NEXT_PUBLIC_MARKETPLACE_CONFIG_URL: yup
+ .array()
+ .json()
+ .of(marketplaceAppSchema)
+ .when('NEXT_PUBLIC_MARKETPLACE_ENABLED', {
+ is: true,
+ then: (schema) => schema,
+ // eslint-disable-next-line max-len
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_MARKETPLACE_CONFIG_URL cannot not be used without NEXT_PUBLIC_MARKETPLACE_ENABLED'),
+ }),
+ NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL: yup
+ .array()
+ .json()
+ .of(yup.string())
+ .when('NEXT_PUBLIC_MARKETPLACE_ENABLED', {
+ is: true,
+ then: (schema) => schema,
+ // eslint-disable-next-line max-len
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL cannot not be used without NEXT_PUBLIC_MARKETPLACE_ENABLED'),
+ }),
+ NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM: yup
+ .string()
+ .when('NEXT_PUBLIC_MARKETPLACE_ENABLED', {
+ is: true,
+ then: (schema) => schema.test(urlTest).required(),
+ // eslint-disable-next-line max-len
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM cannot not be used without NEXT_PUBLIC_MARKETPLACE_ENABLED'),
+ }),
+ NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM: yup
+ .string()
+ .when('NEXT_PUBLIC_MARKETPLACE_ENABLED', {
+ is: true,
+ then: (schema) => schema.test(urlTest),
+ // eslint-disable-next-line max-len
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM cannot not be used without NEXT_PUBLIC_MARKETPLACE_ENABLED'),
+ }),
+ NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL: yup
+ .array()
+ .json()
+ .of(securityReportSchema)
+ .when('NEXT_PUBLIC_MARKETPLACE_ENABLED', {
+ is: true,
+ then: (schema) => schema,
+ // eslint-disable-next-line max-len
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL cannot not be used without NEXT_PUBLIC_MARKETPLACE_ENABLED'),
+ }),
+ NEXT_PUBLIC_MARKETPLACE_FEATURED_APP: yup
+ .string()
+ .when('NEXT_PUBLIC_MARKETPLACE_ENABLED', {
+ is: true,
+ then: (schema) => schema,
+ // eslint-disable-next-line max-len
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_MARKETPLACE_FEATURED_APP cannot not be used without NEXT_PUBLIC_MARKETPLACE_ENABLED'),
+ }),
+ NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL: yup
+ .string()
+ .when('NEXT_PUBLIC_MARKETPLACE_ENABLED', {
+ is: true,
+ then: (schema) => schema.test(urlTest),
+ // eslint-disable-next-line max-len
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL cannot not be used without NEXT_PUBLIC_MARKETPLACE_ENABLED'),
+ }),
+ NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL: yup
+ .string()
+ .when('NEXT_PUBLIC_MARKETPLACE_ENABLED', {
+ is: true,
+ then: (schema) => schema.test(urlTest),
+ // eslint-disable-next-line max-len
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL cannot not be used without NEXT_PUBLIC_MARKETPLACE_ENABLED'),
+ }),
+ NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_API_KEY: yup
+ .string()
+ .when('NEXT_PUBLIC_MARKETPLACE_ENABLED', {
+ is: true,
+ then: (schema) => schema,
+ // eslint-disable-next-line max-len
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_API_KEY cannot not be used without NEXT_PUBLIC_MARKETPLACE_ENABLED'),
+ }),
+ NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID: yup
+ .string()
+ .when('NEXT_PUBLIC_MARKETPLACE_ENABLED', {
+ is: true,
+ then: (schema) => schema,
+ // eslint-disable-next-line max-len
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID cannot not be used without NEXT_PUBLIC_MARKETPLACE_ENABLED'),
+ }),
+ NEXT_PUBLIC_MARKETPLACE_GRAPH_LINKS_URL: yup
+ .string()
+ .when('NEXT_PUBLIC_MARKETPLACE_ENABLED', {
+ is: true,
+ then: (schema) => schema,
+ // eslint-disable-next-line max-len
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_MARKETPLACE_GRAPH_LINKS_URL cannot not be used without NEXT_PUBLIC_MARKETPLACE_ENABLED'),
+ }),
+ });
+
+const beaconChainSchema = yup
+ .object()
+ .shape({
+ NEXT_PUBLIC_HAS_BEACON_CHAIN: yup.boolean(),
+ NEXT_PUBLIC_BEACON_CHAIN_CURRENCY_SYMBOL: yup
+ .string()
+ .when('NEXT_PUBLIC_HAS_BEACON_CHAIN', {
+ is: (value: boolean) => value,
+ then: (schema) => schema.min(1).optional(),
+ otherwise: (schema) => schema.max(
+ -1,
+ 'NEXT_PUBLIC_BEACON_CHAIN_CURRENCY_SYMBOL cannot not be used if NEXT_PUBLIC_HAS_BEACON_CHAIN is not set to "true"',
+ ),
+ }),
+ });
+
+const parentChainCurrencySchema = yup
+ .object()
+ .shape({
+ name: yup.string().required(),
+ symbol: yup.string().required(),
+ decimals: yup.number().required(),
+ });
+
+const parentChainSchema = yup
+ .object()
+ .transform(replaceQuotes)
+ .json()
+ .shape({
+ id: yup.number(),
+ name: yup.string(),
+ baseUrl: yup.string().test(urlTest).required(),
+ rpcUrls: yup.array().of(yup.string().test(urlTest)),
+ currency: yup
+ .mixed()
+ .test(
+ 'shape',
+ (ctx) => {
+ try {
+ parentChainCurrencySchema.validateSync(ctx.originalValue);
+ throw new Error('Unknown validation error');
+ } catch (error: unknown) {
+ const message = getYupValidationErrorMessage(error);
+ return 'in \"currency\" property ' + (message ? `${ message }` : '');
+ }
+ },
+ (data) => {
+ const isUndefined = data === undefined;
+ return isUndefined || parentChainCurrencySchema.isValidSync(data);
+ },
+ ),
+ isTestnet: yup.boolean(),
+ });
+
+const rollupSchema = yup
+ .object()
+ .shape({
+ NEXT_PUBLIC_ROLLUP_TYPE: yup.string().oneOf(ROLLUP_TYPES),
+ NEXT_PUBLIC_ROLLUP_L1_BASE_URL: yup
+ .string()
+ .when('NEXT_PUBLIC_ROLLUP_TYPE', {
+ is: (value: string) => value,
+ then: (schema) => schema.test(urlTest).required(),
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_ROLLUP_L1_BASE_URL cannot not be used if NEXT_PUBLIC_ROLLUP_TYPE is not defined'),
+ }),
+ NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL: yup
+ .string()
+ .when('NEXT_PUBLIC_ROLLUP_TYPE', {
+ is: (value: string) => value === 'optimistic',
+ then: (schema) => schema.test(urlTest).required(),
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL can be used only if NEXT_PUBLIC_ROLLUP_TYPE is set to \'optimistic\' '),
+ }),
+ NEXT_PUBLIC_ROLLUP_OUTPUT_ROOTS_ENABLED: yup
+ .boolean()
+ .when('NEXT_PUBLIC_ROLLUP_TYPE', {
+ is: 'optimistic',
+ then: (schema) => schema,
+ otherwise: (schema) => schema.test(
+ 'not-exist',
+ 'NEXT_PUBLIC_ROLLUP_OUTPUT_ROOTS_ENABLED can only be used if NEXT_PUBLIC_ROLLUP_TYPE is set to \'optimistic\' ',
+ value => value === undefined,
+ ),
+ }),
+ NEXT_PUBLIC_INTEROP_ENABLED: yup
+ .boolean()
+ .when('NEXT_PUBLIC_ROLLUP_TYPE', {
+ is: 'optimistic',
+ then: (schema) => schema,
+ otherwise: (schema) => schema.test(
+ 'not-exist',
+ 'NEXT_PUBLIC_INTEROP_ENABLED can only be used if NEXT_PUBLIC_ROLLUP_TYPE is set to \'optimistic\' ',
+ value => value === undefined,
+ ),
+ }),
+ NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME: yup
+ .string()
+ .when('NEXT_PUBLIC_ROLLUP_TYPE', {
+ is: 'arbitrum',
+ then: (schema) => schema,
+ otherwise: (schema) => schema.test(
+ 'not-exist',
+ 'NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME can only be used if NEXT_PUBLIC_ROLLUP_TYPE is set to \'arbitrum\' ',
+ value => value === undefined,
+ ),
+ }),
+ NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS: yup
+ .boolean()
+ .when('NEXT_PUBLIC_ROLLUP_TYPE', {
+ is: (value: string) => value,
+ then: (schema) => schema,
+ otherwise: (schema) => schema.test(
+ 'not-exist',
+ 'NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS cannot not be used if NEXT_PUBLIC_ROLLUP_TYPE is not defined',
+ value => value === undefined,
+ ),
+ }),
+ NEXT_PUBLIC_ROLLUP_PARENT_CHAIN: yup
+ .mixed()
+ .when('NEXT_PUBLIC_ROLLUP_TYPE', {
+ is: (value: string) => value,
+ then: (schema) => {
+ return schema.test(
+ 'shape',
+ (ctx) => {
+ try {
+ parentChainSchema.validateSync(ctx.originalValue);
+ throw new Error('Unknown validation error');
+ } catch (error: unknown) {
+ const message = getYupValidationErrorMessage(error);
+ return 'Invalid schema were provided for NEXT_PUBLIC_ROLLUP_TYPE' + (message ? `: ${ message }` : '');
+ }
+ },
+ (data) => {
+ const isUndefined = data === undefined;
+ return isUndefined || parentChainSchema.isValidSync(data);
+ }
+ )
+ },
+ otherwise: (schema) => schema.test(
+ 'not-exist',
+ 'NEXT_PUBLIC_ROLLUP_PARENT_CHAIN cannot not be used if NEXT_PUBLIC_ROLLUP_TYPE is not defined',
+ value => value === undefined,
+ ),
+ }),
+ NEXT_PUBLIC_ROLLUP_DA_CELESTIA_NAMESPACE: yup
+ .string()
+ .min(60)
+ .max(60)
+ .matches(regexp.HEX_REGEXP_WITH_0X)
+ .when('NEXT_PUBLIC_ROLLUP_TYPE', {
+ is: (value: string) => value === 'arbitrum',
+ then: (schema) => schema,
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_ROLLUP_DA_CELESTIA_NAMESPACE can only be used if NEXT_PUBLIC_ROLLUP_TYPE is set to \'arbitrum\' '),
+ }),
+ NEXT_PUBLIC_ROLLUP_DA_CELESTIA_CELENIUM_URL: yup
+ .string()
+ .test(urlTest)
+ .when('NEXT_PUBLIC_ROLLUP_TYPE', {
+ is: (value: string) => value === 'arbitrum' || value === 'optimistic',
+ then: (schema) => schema,
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_ROLLUP_DA_CELESTIA_CELENIUM_URL can only be used if NEXT_PUBLIC_ROLLUP_TYPE is set to \'arbitrum\' or \'optimistic\''),
+ }),
+ });
+
+const celoSchema = yup
+ .object()
+ .shape({
+ NEXT_PUBLIC_CELO_ENABLED: yup.boolean(),
+ NEXT_PUBLIC_CELO_L2_UPGRADE_BLOCK: yup
+ .string()
+ .when('NEXT_PUBLIC_CELO_ENABLED', {
+ is: (value: boolean) => value,
+ then: (schema) => schema.min(0).optional(),
+ otherwise: (schema) => schema.max(
+ -1,
+ 'NEXT_PUBLIC_CELO_L2_UPGRADE_BLOCK cannot not be used if NEXT_PUBLIC_CELO_ENABLED is not set to "true"',
+ ),
+ }),
+ });
+
+const adButlerConfigSchema = yup
+ .object()
+ .transform(replaceQuotes)
+ .json()
+ .when('NEXT_PUBLIC_AD_BANNER_PROVIDER', {
+ is: (value: AdBannerProviders) => value === 'adbutler',
+ then: (schema) => schema
+ .shape({
+ id: yup.string().required(),
+ width: yup.number().positive().required(),
+ height: yup.number().positive().required(),
+ })
+ .required(),
+ })
+ .when('NEXT_PUBLIC_AD_BANNER_ADDITIONAL_PROVIDER', {
+ is: (value: AdBannerProviders) => value === 'adbutler',
+ then: (schema) => schema
+ .shape({
+ id: yup.string().required(),
+ width: yup.number().positive().required(),
+ height: yup.number().positive().required(),
+ })
+ .required(),
+ });
+
+const adsBannerSchema = yup
+ .object()
+ .shape({
+ NEXT_PUBLIC_AD_BANNER_PROVIDER: yup.string().oneOf(SUPPORTED_AD_BANNER_PROVIDERS),
+ NEXT_PUBLIC_AD_BANNER_ADDITIONAL_PROVIDER: yup.string().oneOf(SUPPORTED_AD_BANNER_ADDITIONAL_PROVIDERS),
+ NEXT_PUBLIC_AD_ADBUTLER_CONFIG_DESKTOP: adButlerConfigSchema,
+ NEXT_PUBLIC_AD_ADBUTLER_CONFIG_MOBILE: adButlerConfigSchema,
+ });
+
+// DEPRECATED
+const sentrySchema = yup
+ .object()
+ .shape({
+ NEXT_PUBLIC_SENTRY_DSN: yup.string().test(urlTest),
+ SENTRY_CSP_REPORT_URI: yup
+ .string()
+ .when('NEXT_PUBLIC_SENTRY_DSN', {
+ is: (value: string) => Boolean(value),
+ then: (schema) => schema.test(urlTest),
+ otherwise: (schema) => schema.max(-1, 'SENTRY_CSP_REPORT_URI cannot not be used without NEXT_PUBLIC_SENTRY_DSN'),
+ }),
+ NEXT_PUBLIC_SENTRY_ENABLE_TRACING: yup
+ .boolean()
+ .when('NEXT_PUBLIC_SENTRY_DSN', {
+ is: (value: string) => Boolean(value),
+ then: (schema) => schema,
+ }),
+ });
+
+const accountSchema = yup
+ .object()
+ .shape({
+ NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED: yup.boolean(),
+ NEXT_PUBLIC_AUTH0_CLIENT_ID: yup
+ .string()
+ .when('NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED', {
+ is: (value: boolean) => value,
+ then: (schema) => schema,
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_AUTH0_CLIENT_ID cannot not be used if NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED is not set to "true"'),
+ }),
+ NEXT_PUBLIC_AUTH_URL: yup
+ .string()
+ .when('NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED', {
+ is: (value: boolean) => value,
+ then: (schema) => schema.test(urlTest),
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_AUTH_URL cannot not be used if NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED is not set to "true"'),
+ }),
+ NEXT_PUBLIC_LOGOUT_URL: yup
+ .string()
+ .when('NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED', {
+ is: (value: boolean) => value,
+ then: (schema) => schema.test(urlTest),
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_LOGOUT_URL cannot not be used if NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED is not set to "true"'),
+ }),
+ });
+
+const featuredNetworkSchema: yup.ObjectSchema = yup
+ .object()
+ .shape({
+ title: yup.string().required(),
+ url: yup.string().test(urlTest).required(),
+ group: yup.string().oneOf(NETWORK_GROUPS).required(),
+ icon: yup.string().test(urlTest),
+ isActive: yup.boolean(),
+ invertIconInDarkMode: yup.boolean(),
+ });
+
+const navItemExternalSchema: yup.ObjectSchema = yup
+ .object({
+ text: yup.string().required(),
+ url: yup.string().test(urlTest).required(),
+ });
+
+const fontFamilySchema: yup.ObjectSchema = yup
+ .object()
+ .transform(replaceQuotes)
+ .json()
+ .shape({
+ name: yup.string().required(),
+ url: yup.string().test(urlTest).required(),
+ });
+
+const heroBannerButtonStateSchema: yup.ObjectSchema = yup.object({
+ background: yup.array().max(2).of(yup.string()),
+ text_color: yup.array().max(2).of(yup.string()),
+});
+
+const heroBannerSchema: yup.ObjectSchema = yup.object()
+ .transform(replaceQuotes)
+ .json()
+ .shape({
+ background: yup.array().max(2).of(yup.string()),
+ text_color: yup.array().max(2).of(yup.string()),
+ border: yup.array().max(2).of(yup.string()),
+ button: yup.object({
+ _default: heroBannerButtonStateSchema,
+ _hover: heroBannerButtonStateSchema,
+ _selected: heroBannerButtonStateSchema,
+ }),
+ });
+
+const footerLinkSchema: yup.ObjectSchema = yup
+ .object({
+ text: yup.string().required(),
+ url: yup.string().test(urlTest).required(),
+ });
+
+const footerLinkGroupSchema: yup.ObjectSchema = yup
+ .object({
+ title: yup.string().required(),
+ links: yup
+ .array()
+ .of(footerLinkSchema)
+ .required(),
+ });
+
+const networkExplorerSchema: yup.ObjectSchema = yup
+ .object({
+ title: yup.string().required(),
+ logo: yup.string().test(urlTest),
+ baseUrl: yup.string().test(urlTest).required(),
+ paths: yup
+ .object()
+ .shape({
+ tx: yup.string(),
+ address: yup.string(),
+ token: yup.string(),
+ block: yup.string(),
+ }),
+ });
+
+const contractCodeIdeSchema: yup.ObjectSchema = yup
+ .object({
+ title: yup.string().required(),
+ url: yup.string().test(urlTest).required(),
+ icon_url: yup.string().test(urlTest).required(),
+ });
+
+const nftMarketplaceSchema: yup.ObjectSchema = yup
+ .object({
+ name: yup.string().required(),
+ collection_url: yup.string().test(urlTest).required(),
+ instance_url: yup.string().test(urlTest).required(),
+ logo_url: yup.string().test(urlTest).required(),
+ });
+
+const bridgedTokenChainSchema: yup.ObjectSchema = yup
+ .object({
+ id: yup.string().required(),
+ title: yup.string().required(),
+ short_title: yup.string().required(),
+ base_url: yup.string().test(urlTest).required(),
+ });
+
+const tokenBridgeSchema: yup.ObjectSchema = yup
+ .object({
+ type: yup.string().required(),
+ title: yup.string().required(),
+ short_title: yup.string().required(),
+ });
+
+const bridgedTokensSchema = yup
+ .object()
+ .shape({
+ NEXT_PUBLIC_BRIDGED_TOKENS_CHAINS: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(bridgedTokenChainSchema),
+ NEXT_PUBLIC_BRIDGED_TOKENS_BRIDGES: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(tokenBridgeSchema)
+ .when('NEXT_PUBLIC_BRIDGED_TOKENS_CHAINS', {
+ is: (value: Array) => value && value.length > 0,
+ then: (schema) => schema.required(),
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_BRIDGED_TOKENS_BRIDGES cannot not be used without NEXT_PUBLIC_BRIDGED_TOKENS_CHAINS'),
+ }),
+ });
+
+const deFiDropdownItemSchema: yup.ObjectSchema = yup
+ .object({
+ text: yup.string().required(),
+ icon: yup.string().required(),
+ dappId: yup.string(),
+ url: yup.string().test(urlTest),
+ })
+ .test('oneOfRequired', 'NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS: Either dappId or url is required', function(value) {
+ return Boolean(value.dappId) || Boolean(value.url);
+ }) as yup.ObjectSchema;
+
+const multichainProviderConfigSchema: yup.ObjectSchema = yup.object({
+ name: yup.string().required(),
+ url_template: yup.string().required(),
+ logo: yup.string().required(),
+ dapp_id: yup.string(),
+});
+
+const externalTxsConfigSchema: yup.ObjectSchema = yup.object({
+ chain_name: yup.string().required(),
+ chain_logo_url: yup.string().required(),
+ explorer_url_template: yup.string().required(),
+});
+
+const schema = yup
+ .object()
+ .noUnknown(true, (params) => {
+ return `Unknown ENV variables were provided: ${ params.unknown }`;
+ })
+ .shape({
+ // I. Build-time ENVs
+ // -----------------
+ NEXT_PUBLIC_GIT_TAG: yup.string(),
+ NEXT_PUBLIC_GIT_COMMIT_SHA: yup.string(),
+
+ // II. Run-time ENVs
+ // -----------------
+ // 1. App configuration
+ NEXT_PUBLIC_APP_HOST: yup.string().required(),
+ NEXT_PUBLIC_APP_PROTOCOL: yup.string().oneOf(protocols),
+ NEXT_PUBLIC_APP_PORT: yup.number().positive().integer(),
+ NEXT_PUBLIC_APP_ENV: yup.string(),
+ NEXT_PUBLIC_APP_INSTANCE: yup.string(),
+
+ // 2. Blockchain parameters
+ NEXT_PUBLIC_NETWORK_NAME: yup.string().required(),
+ NEXT_PUBLIC_NETWORK_SHORT_NAME: yup.string(),
+ NEXT_PUBLIC_NETWORK_ID: yup.number().positive().integer().required(),
+ NEXT_PUBLIC_NETWORK_RPC_URL: yup
+ .mixed()
+ .test(
+ 'shape',
+ 'Invalid schema were provided for NEXT_PUBLIC_NETWORK_RPC_URL, it should be either array of URLs or URL string',
+ (data) => {
+ const isUrlSchema = yup.string().test(urlTest);
+ const isArrayOfUrlsSchema = yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(yup.string().test(urlTest));
+
+ return isUrlSchema.isValidSync(data) || isArrayOfUrlsSchema.isValidSync(data);
+ }),
+ NEXT_PUBLIC_NETWORK_CURRENCY_NAME: yup.string(),
+ NEXT_PUBLIC_NETWORK_CURRENCY_WEI_NAME: yup.string(),
+ NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL: yup.string(),
+ NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS: yup.number().integer().positive(),
+ NEXT_PUBLIC_NETWORK_SECONDARY_COIN_SYMBOL: yup.string(),
+ NEXT_PUBLIC_NETWORK_MULTIPLE_GAS_CURRENCIES: yup.boolean(),
+ NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE: yup
+ .string().oneOf([ 'validation', 'mining' ])
+ .when('NEXT_PUBLIC_ROLLUP_TYPE', {
+ is: (value: string) => value === 'arbitrum' || value === 'zkEvm',
+ then: (schema) => schema.test(
+ 'not-exist',
+ 'NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE can not be set for Arbitrum and ZkEVM rollups',
+ value => value === undefined,
+ ),
+ otherwise: (schema) => schema,
+ }),
+ NEXT_PUBLIC_NETWORK_TOKEN_STANDARD_NAME: yup.string(),
+ NEXT_PUBLIC_IS_TESTNET: yup.boolean(),
+
+ // 3. API configuration
+ NEXT_PUBLIC_API_PROTOCOL: yup.string().oneOf(protocols),
+ NEXT_PUBLIC_API_HOST: yup.string().required(),
+ NEXT_PUBLIC_API_PORT: yup.number().integer().positive(),
+ NEXT_PUBLIC_API_BASE_PATH: yup.string(),
+ NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL: yup.string().oneOf([ 'ws', 'wss' ]),
+
+ // 4. UI configuration
+ // a. homepage
+ NEXT_PUBLIC_HOMEPAGE_CHARTS: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(yup.string().oneOf(CHAIN_INDICATOR_IDS))
+ .test(
+ 'stats-api-required',
+ 'NEXT_PUBLIC_STATS_API_HOST is required when daily_operational_txs is enabled in NEXT_PUBLIC_HOMEPAGE_CHARTS',
+ function(value) {
+ // daily_operational_txs is presented only in stats microservice
+ if (value?.includes('daily_operational_txs')) {
+ return Boolean(this.parent.NEXT_PUBLIC_STATS_API_HOST);
+ }
+ return true;
+ }
+ ),
+ NEXT_PUBLIC_HOMEPAGE_STATS: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(yup.string().oneOf(HOME_STATS_WIDGET_IDS))
+ .test(
+ 'stats-api-required',
+ 'NEXT_PUBLIC_STATS_API_HOST is required when total_operational_txs is enabled in NEXT_PUBLIC_HOMEPAGE_STATS',
+ function(value) {
+ // total_operational_txs is presented only in stats microservice
+ if (value?.includes('total_operational_txs')) {
+ return Boolean(this.parent.NEXT_PUBLIC_STATS_API_HOST);
+ }
+ return true;
+ }
+ ),
+ NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR: yup.string(),
+ NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND: yup.string(),
+ NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG: yup
+ .mixed()
+ .test(
+ 'shape',
+ (ctx) => {
+ try {
+ heroBannerSchema.validateSync(ctx.originalValue);
+ throw new Error('Unknown validation error');
+ } catch (error: unknown) {
+ const message = getYupValidationErrorMessage(error);
+ return 'Invalid schema were provided for NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG' + (message ? `: ${ message }` : '');
+ }
+ },
+ (data) => {
+ const isUndefined = data === undefined;
+ return isUndefined || heroBannerSchema.isValidSync(data);
+ }),
+
+ // b. sidebar
+ NEXT_PUBLIC_FEATURED_NETWORKS: yup
+ .array()
+ .json()
+ .of(featuredNetworkSchema),
+ NEXT_PUBLIC_OTHER_LINKS: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(navItemExternalSchema),
+ NEXT_PUBLIC_NAVIGATION_HIDDEN_LINKS: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(yup.string().oneOf(NAVIGATION_LINK_IDS)),
+ NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(yup.string()),
+ NEXT_PUBLIC_NAVIGATION_LAYOUT: yup.string().oneOf([ 'horizontal', 'vertical' ]),
+ NEXT_PUBLIC_NETWORK_LOGO: yup.string().test(urlTest),
+ NEXT_PUBLIC_NETWORK_LOGO_DARK: yup.string().test(urlTest),
+ NEXT_PUBLIC_NETWORK_ICON: yup.string().test(urlTest),
+ NEXT_PUBLIC_NETWORK_ICON_DARK: yup.string().test(urlTest),
+
+ // c. footer
+ NEXT_PUBLIC_FOOTER_LINKS: yup
+ .array()
+ .json()
+ .of(footerLinkGroupSchema),
+
+ // d. views
+ NEXT_PUBLIC_VIEWS_BLOCK_HIDDEN_FIELDS: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(yup.string().oneOf(BLOCK_FIELDS_IDS)),
+ NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE: yup.string().oneOf(IDENTICON_TYPES),
+ NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(yup.string().oneOf(ADDRESS_FORMATS)),
+ NEXT_PUBLIC_VIEWS_ADDRESS_BECH_32_PREFIX: yup
+ .string()
+ .when('NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT', {
+ is: (value: Array | undefined) => value && value.includes('bech32'),
+ then: (schema) => schema.required().min(1).max(83),
+ otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_VIEWS_ADDRESS_BECH_32_PREFIX is required if NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT contains "bech32"'),
+ }),
+
+ NEXT_PUBLIC_VIEWS_ADDRESS_HIDDEN_VIEWS: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(yup.string().oneOf(ADDRESS_VIEWS_IDS)),
+ NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED: yup.boolean(),
+ NEXT_PUBLIC_VIEWS_CONTRACT_EXTRA_VERIFICATION_METHODS: yup
+ .mixed()
+ .test(
+ 'shape',
+ 'Invalid schema were provided for NEXT_PUBLIC_VIEWS_CONTRACT_EXTRA_VERIFICATION_METHODS, it should be either array of method ids or "none" string literal',
+ (data) => {
+ const isNoneSchema = yup.string().oneOf([ 'none' ]);
+ const isArrayOfMethodsSchema = yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(yup.string().oneOf(SMART_CONTRACT_EXTRA_VERIFICATION_METHODS));
+
+ return isNoneSchema.isValidSync(data) || isArrayOfMethodsSchema.isValidSync(data);
+ }),
+ NEXT_PUBLIC_VIEWS_CONTRACT_LANGUAGE_FILTERS: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(yup.string().oneOf(SMART_CONTRACT_LANGUAGE_FILTERS)),
+
+ NEXT_PUBLIC_VIEWS_TX_HIDDEN_FIELDS: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(yup.string().oneOf(TX_FIELDS_IDS)),
+ NEXT_PUBLIC_VIEWS_TX_ADDITIONAL_FIELDS: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(yup.string().oneOf(TX_ADDITIONAL_FIELDS_IDS)),
+ NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(nftMarketplaceSchema),
+ NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED: yup.boolean(),
+ NEXT_PUBLIC_HELIA_VERIFIED_FETCH_ENABLED: yup.boolean(),
+
+ // e. misc
+ NEXT_PUBLIC_NETWORK_EXPLORERS: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(networkExplorerSchema),
+ NEXT_PUBLIC_CONTRACT_CODE_IDES: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(contractCodeIdeSchema),
+ NEXT_PUBLIC_HAS_CONTRACT_AUDIT_REPORTS: yup.boolean(),
+ NEXT_PUBLIC_HIDE_INDEXING_ALERT_BLOCKS: yup.boolean(),
+ NEXT_PUBLIC_HIDE_INDEXING_ALERT_INT_TXS: yup.boolean(),
+ NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE: yup.string(),
+ NEXT_PUBLIC_COLOR_THEME_DEFAULT: yup.string().oneOf(COLOR_THEME_IDS),
+ NEXT_PUBLIC_FONT_FAMILY_HEADING: yup
+ .mixed()
+ .test('shape', 'Invalid schema were provided for NEXT_PUBLIC_FONT_FAMILY_HEADING', (data) => {
+ const isUndefined = data === undefined;
+ return isUndefined || fontFamilySchema.isValidSync(data);
+ }),
+ NEXT_PUBLIC_FONT_FAMILY_BODY: yup
+ .mixed()
+ .test('shape', 'Invalid schema were provided for NEXT_PUBLIC_FONT_FAMILY_BODY', (data) => {
+ const isUndefined = data === undefined;
+ return isUndefined || fontFamilySchema.isValidSync(data);
+ }),
+ NEXT_PUBLIC_MAX_CONTENT_WIDTH_ENABLED: yup.boolean(),
+
+ // 5. Features configuration
+ NEXT_PUBLIC_API_SPEC_URL: yup
+ .mixed()
+ .test('shape', 'Invalid schema were provided for NEXT_PUBLIC_API_SPEC_URL, it should be either URL-string or "none" string literal', (data) => {
+ const isNoneSchema = yup.string().oneOf([ 'none' ]);
+ const isUrlStringSchema = yup.string().test(urlTest);
+
+ return isNoneSchema.isValidSync(data) || isUrlStringSchema.isValidSync(data);
+ }),
+ NEXT_PUBLIC_STATS_API_HOST: yup.string().test(urlTest),
+ NEXT_PUBLIC_STATS_API_BASE_PATH: yup.string(),
+ NEXT_PUBLIC_VISUALIZE_API_HOST: yup.string().test(urlTest),
+ NEXT_PUBLIC_VISUALIZE_API_BASE_PATH: yup.string(),
+ NEXT_PUBLIC_CONTRACT_INFO_API_HOST: yup.string().test(urlTest),
+ NEXT_PUBLIC_NAME_SERVICE_API_HOST: yup.string().test(urlTest),
+ NEXT_PUBLIC_METADATA_SERVICE_API_HOST: yup.string().test(urlTest),
+ NEXT_PUBLIC_ADMIN_SERVICE_API_HOST: yup.string().test(urlTest),
+ NEXT_PUBLIC_GRAPHIQL_TRANSACTION: yup
+ .mixed()
+ .test('shape', 'Invalid schema were provided for NEXT_PUBLIC_GRAPHIQL_TRANSACTION, it should be either Hex-string or "none" string literal', (data) => {
+ const isNoneSchema = yup.string().oneOf([ 'none' ]);
+ const isHashStringSchema = yup.string().matches(regexp.HEX_REGEXP);
+
+ return isNoneSchema.isValidSync(data) || isHashStringSchema.isValidSync(data);
+ }),
+ NEXT_PUBLIC_WEB3_WALLETS: yup
+ .mixed()
+ .test('shape', 'Invalid schema were provided for NEXT_PUBLIC_WEB3_WALLETS, it should be either array or "none" string literal', (data) => {
+ const isNoneSchema = yup.string().equals([ 'none' ]);
+ const isArrayOfWalletsSchema = yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(yup.string().oneOf(SUPPORTED_WALLETS));
+
+ return isNoneSchema.isValidSync(data) || isArrayOfWalletsSchema.isValidSync(data);
+ }),
+ NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET: yup.boolean(),
+ NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER: yup.string().oneOf(TX_INTERPRETATION_PROVIDERS),
+ NEXT_PUBLIC_AD_TEXT_PROVIDER: yup.string().oneOf(SUPPORTED_AD_TEXT_PROVIDERS),
+ NEXT_PUBLIC_PROMOTE_BLOCKSCOUT_IN_TITLE: yup.boolean(),
+ NEXT_PUBLIC_OG_DESCRIPTION: yup.string(),
+ NEXT_PUBLIC_OG_IMAGE_URL: yup.string().test(urlTest),
+ NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED: yup.boolean(),
+ NEXT_PUBLIC_SEO_ENHANCED_DATA_ENABLED: yup.boolean(),
+ NEXT_PUBLIC_SAFE_TX_SERVICE_URL: yup.string().test(urlTest),
+ NEXT_PUBLIC_IS_SUAVE_CHAIN: yup.boolean(),
+ NEXT_PUBLIC_HAS_USER_OPS: yup.boolean(),
+ NEXT_PUBLIC_METASUITES_ENABLED: yup.boolean(),
+ NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(multichainProviderConfigSchema),
+ NEXT_PUBLIC_GAS_REFUEL_PROVIDER_CONFIG: yup
+ .mixed()
+ .test('shape', 'Invalid schema were provided for NEXT_PUBLIC_GAS_REFUEL_PROVIDER_CONFIG, it should have name and url template', (data) => {
+ const isUndefined = data === undefined;
+ const valueSchema = yup.object().transform(replaceQuotes).json().shape({
+ name: yup.string().required(),
+ url_template: yup.string().required(),
+ logo: yup.string(),
+ dapp_id: yup.string(),
+ });
+
+ return isUndefined || valueSchema.isValidSync(data);
+ }),
+ NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE: yup.string().oneOf(VALIDATORS_CHAIN_TYPE),
+ NEXT_PUBLIC_GAS_TRACKER_ENABLED: yup.boolean(),
+ NEXT_PUBLIC_GAS_TRACKER_UNITS: yup.array().transform(replaceQuotes).json().of(yup.string().oneOf(GAS_UNITS)),
+ NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED: yup.boolean(),
+ NEXT_PUBLIC_ADVANCED_FILTER_ENABLED: yup.boolean(),
+ NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS: yup
+ .array()
+ .transform(replaceQuotes)
+ .json()
+ .of(deFiDropdownItemSchema),
+ NEXT_PUBLIC_FAULT_PROOF_ENABLED: yup.boolean()
+ .when('NEXT_PUBLIC_ROLLUP_TYPE', {
+ is: 'optimistic',
+ then: (schema) => schema,
+ otherwise: (schema) => schema.test(
+ 'not-exist',
+ 'NEXT_PUBLIC_FAULT_PROOF_ENABLED can only be used with NEXT_PUBLIC_ROLLUP_TYPE=optimistic',
+ value => value === undefined,
+ ),
+ }),
+ NEXT_PUBLIC_HAS_MUD_FRAMEWORK: yup.boolean()
+ .when('NEXT_PUBLIC_ROLLUP_TYPE', {
+ is: 'optimistic',
+ then: (schema) => schema,
+ otherwise: (schema) => schema.test(
+ 'not-exist',
+ 'NEXT_PUBLIC_HAS_MUD_FRAMEWORK can only be used with NEXT_PUBLIC_ROLLUP_TYPE=optimistic',
+ value => value === undefined,
+ ),
+ }),
+ NEXT_PUBLIC_DEX_POOLS_ENABLED: yup.boolean()
+ .when('NEXT_PUBLIC_CONTRACT_INFO_API_HOST', {
+ is: (value: string) => Boolean(value),
+ then: (schema) => schema,
+ otherwise: (schema) => schema.test(
+ 'not-exist',
+ 'NEXT_PUBLIC_DEX_POOLS_ENABLED can only be used with NEXT_PUBLIC_CONTRACT_INFO_API_HOST',
+ value => value === undefined,
+ ),
+ }),
+ NEXT_PUBLIC_SAVE_ON_GAS_ENABLED: yup.boolean(),
+ NEXT_PUBLIC_ADDRESS_USERNAME_TAG: yup
+ .mixed()
+ .test('shape', 'Invalid schema were provided for NEXT_PUBLIC_ADDRESS_USERNAME_TAG, it should have api_url_template', (data) => {
+ const isUndefined = data === undefined;
+ const valueSchema = yup.object().transform(replaceQuotes).json().shape({
+ api_url_template: yup.string().required(),
+ tag_link_template: yup.string(),
+ tag_icon: yup.string(),
+ tag_bg_color: yup.string(),
+ tag_text_color: yup.string(),
+ });
+
+ return isUndefined || valueSchema.isValidSync(data);
+ }),
+ NEXT_PUBLIC_REWARDS_SERVICE_API_HOST: yup.string().test(urlTest),
+ NEXT_PUBLIC_XSTAR_SCORE_URL: yup.string().test(urlTest),
+ NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK: yup.string().test(urlTest),
+ NEXT_PUBLIC_TX_EXTERNAL_TRANSACTIONS_CONFIG: yup.mixed().test(
+ 'shape',
+ 'Invalid schema were provided for NEXT_PUBLIC_TX_EXTERNAL_TRANSACTIONS_CONFIG, it should have chain_name, chain_logo_url, and explorer_url_template',
+ (data) => {
+ const isUndefined = data === undefined;
+ const valueSchema = yup.object().transform(replaceQuotes).json().shape({
+ chain_name: yup.string().required(),
+ chain_logo_url: yup.string().required(),
+ explorer_url_template: yup.string().required(),
+ });
+
+ return isUndefined || valueSchema.isValidSync(data);
+ }),
+
+ // 6. External services envs
+ NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: yup.string(),
+ NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY: yup.string(),
+ NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY: yup.string(), // DEPRECATED
+ NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID: yup.string(),
+ NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN: yup.string(),
+ NEXT_PUBLIC_GROWTH_BOOK_CLIENT_KEY: yup.string(),
+ NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN: yup.string(),
+
+ // Misc
+ NEXT_PUBLIC_USE_NEXT_JS_PROXY: yup.boolean(),
+ })
+ .concat(accountSchema)
+ .concat(adsBannerSchema)
+ .concat(marketplaceSchema)
+ .concat(rollupSchema)
+ .concat(celoSchema)
+ .concat(beaconChainSchema)
+ .concat(bridgedTokensSchema)
+ .concat(sentrySchema);
+
+export default schema;
diff --git a/explorer/frontend/deploy/tools/envs-validator/test.sh b/explorer/frontend/deploy/tools/envs-validator/test.sh
new file mode 100755
index 000000000..46d3ea3fc
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/test.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+test_folder="./test"
+common_file="${test_folder}/.env.common"
+
+# Generate ENV registry file
+export NEXT_PUBLIC_GIT_COMMIT_SHA=$(git rev-parse --short HEAD)
+export NEXT_PUBLIC_GIT_TAG=$(git describe --tags --abbrev=0)
+../../scripts/collect_envs.sh ../../../docs/ENVS.md
+
+# Copy test assets
+mkdir -p "./public/assets/configs"
+cp -r ${test_folder}/assets ./public/
+
+# Build validator script
+yarn build
+
+validate_file() {
+ local test_file="$1"
+
+ echo
+ echo "🧿 Validating file '$test_file'..."
+
+ dotenv \
+ -e $test_file \
+ -e $common_file \
+ yarn run validate -- --silent
+
+ if [ $? -eq 0 ]; then
+ echo "👍 All good!"
+ return 0
+ else
+ echo "🛑 The file is invalid. Please fix errors and run script again."
+ echo
+ return 1
+ fi
+}
+
+test_files=($(find "$test_folder" -maxdepth 1 -type f | grep -vE '\/\.env\.common$'))
+
+for file in "${test_files[@]}"; do
+ validate_file "$file"
+ if [ $? -eq 1 ]; then
+ exit 1
+ fi
+done
diff --git a/explorer/frontend/deploy/tools/envs-validator/test/.env.adbutler b/explorer/frontend/deploy/tools/envs-validator/test/.env.adbutler
new file mode 100644
index 000000000..7877a7740
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/test/.env.adbutler
@@ -0,0 +1,3 @@
+NEXT_PUBLIC_AD_BANNER_PROVIDER=adbutler
+NEXT_PUBLIC_AD_ADBUTLER_CONFIG_DESKTOP={'id':'123456','width':'728','height':'90'}
+NEXT_PUBLIC_AD_ADBUTLER_CONFIG_MOBILE={'id':'654321','width':'300','height':'100'}
\ No newline at end of file
diff --git a/explorer/frontend/deploy/tools/envs-validator/test/.env.adbutler_add b/explorer/frontend/deploy/tools/envs-validator/test/.env.adbutler_add
new file mode 100644
index 000000000..7f1968e4b
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/test/.env.adbutler_add
@@ -0,0 +1,4 @@
+NEXT_PUBLIC_AD_BANNER_PROVIDER='slise'
+NEXT_PUBLIC_AD_BANNER_ADDITIONAL_PROVIDER='adbutler'
+NEXT_PUBLIC_AD_ADBUTLER_CONFIG_DESKTOP={'id':'123456','width':'728','height':'90'}
+NEXT_PUBLIC_AD_ADBUTLER_CONFIG_MOBILE={'id':'654321','width':'300','height':'100'}
\ No newline at end of file
diff --git a/explorer/frontend/deploy/tools/envs-validator/test/.env.alt b/explorer/frontend/deploy/tools/envs-validator/test/.env.alt
new file mode 100644
index 000000000..11e6bf78f
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/test/.env.alt
@@ -0,0 +1,9 @@
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=none
+NEXT_PUBLIC_API_SPEC_URL=none
+NEXT_PUBLIC_VIEWS_CONTRACT_EXTRA_VERIFICATION_METHODS=none
+NEXT_PUBLIC_HOMEPAGE_STATS=[]
+NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT=['base16','bech32']
+NEXT_PUBLIC_VIEWS_ADDRESS_BECH_32_PREFIX=foo
+NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=xxx
+NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY=deprecated
+NEXT_PUBLIC_NETWORK_RPC_URL=['https://example.com','https://example2.com']
diff --git a/explorer/frontend/deploy/tools/envs-validator/test/.env.arbitrum b/explorer/frontend/deploy/tools/envs-validator/test/.env.arbitrum
new file mode 100644
index 000000000..b9767581c
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/test/.env.arbitrum
@@ -0,0 +1,8 @@
+NEXT_PUBLIC_ROLLUP_TYPE=arbitrum
+NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://example.com
+NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS=true
+NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME=DuckChain
+NEXT_PUBLIC_ROLLUP_PARENT_CHAIN={'baseUrl':'https://explorer.duckchain.io','currency':{'name':'Quack','symbol':'QUACK','decimals':18},'isTestnet':true,'id':42,'name':'DuckChain','rpcUrls':['https://rpc.duckchain.io']}
+
+NEXT_PUBLIC_ROLLUP_DA_CELESTIA_NAMESPACE=0x00000000000000000000000000000000000000ca1de12a9905be97beaf
+NEXT_PUBLIC_ROLLUP_DA_CELESTIA_CELENIUM_URL=https://mocha.celenium.io/blob
\ No newline at end of file
diff --git a/explorer/frontend/deploy/tools/envs-validator/test/.env.base b/explorer/frontend/deploy/tools/envs-validator/test/.env.base
new file mode 100644
index 000000000..debb88fd4
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/test/.env.base
@@ -0,0 +1,91 @@
+NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN=https://rollbar.com
+NEXT_PUBLIC_AUTH_URL=https://example.com
+NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
+NEXT_PUBLIC_LOGOUT_URL=https://example.com
+NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=xxx
+NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=xxx
+NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID=UA-XXXXXX-X
+NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN=xxx
+NEXT_PUBLIC_GROWTH_BOOK_CLIENT_KEY=xxx
+NEXT_PUBLIC_AUTH0_CLIENT_ID=xxx
+NEXT_PUBLIC_GROWTH_BOOK_CLIENT_KEY=xxx
+NEXT_PUBLIC_AD_TEXT_PROVIDER=coinzilla
+NEXT_PUBLIC_AD_BANNER_PROVIDER=slise
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://example.com
+NEXT_PUBLIC_API_BASE_PATH=/
+NEXT_PUBLIC_API_SPEC_URL=https://example.com
+NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
+NEXT_PUBLIC_APP_ENV=development
+NEXT_PUBLIC_APP_PORT=3000
+NEXT_PUBLIC_APP_PROTOCOL=http
+NEXT_PUBLIC_BRIDGED_TOKENS_CHAINS=[{'id':'1','title':'Ethereum','short_title':'ETH','base_url':'https://example.com'}]
+NEXT_PUBLIC_BRIDGED_TOKENS_BRIDGES=[{'type':'omni','title':'OmniBridge','short_title':'OMNI'}]
+NEXT_PUBLIC_COLOR_THEME_DEFAULT=dim
+NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.blockscout.com/?address={hash}&blockscout={domain}','icon_url':'https://example.com/icon.svg'}]
+NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://example.com
+NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED=true
+NEXT_PUBLIC_FEATURED_NETWORKS=https://example.com
+NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/accounts','/apps']
+NEXT_PUBLIC_NAVIGATION_LAYOUT=horizontal
+NEXT_PUBLIC_FONT_FAMILY_HEADING={'name':'Montserrat','url':'https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap'}
+NEXT_PUBLIC_FONT_FAMILY_BODY={'name':'Raleway','url':'https://fonts.googleapis.com/css2?family=Raleway:wght@400;500;600;700&display=swap'}
+NEXT_PUBLIC_FOOTER_LINKS=https://example.com
+NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d
+NEXT_PUBLIC_HELIA_VERIFIED_FETCH_ENABLED=false
+NEXT_PUBLIC_HIDE_INDEXING_ALERT_BLOCKS=false
+NEXT_PUBLIC_HIDE_INDEXING_ALERT_INT_TXS=false
+NEXT_PUBLIC_MAX_CONTENT_WIDTH_ENABLED=false
+NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
+NEXT_PUBLIC_HOMEPAGE_STATS=['total_blocks','average_block_time','total_txs','wallet_addresses','gas_tracker','current_epoch']
+NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR='#fff'
+NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND='rgb(255, 145, 0)'
+NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['lightpink'],'text_color':['deepskyblue','white'],'border':['3px solid black']}
+NEXT_PUBLIC_GAS_TRACKER_ENABLED=true
+NEXT_PUBLIC_GAS_TRACKER_UNITS=['gwei']
+NEXT_PUBLIC_IS_TESTNET=true
+NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE='Hello '
+NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://example.com
+NEXT_PUBLIC_METASUITES_ENABLED=true
+NEXT_PUBLIC_NAVIGATION_HIDDEN_LINKS=['eth_rpc_api','rpc_api']
+NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
+NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
+NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
+NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Explorer','baseUrl':'https://example.com/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}]
+NEXT_PUBLIC_NETWORK_SECONDARY_COIN_SYMBOL=GNO
+NEXT_PUBLIC_NETWORK_MULTIPLE_GAS_CURRENCIES=true
+NEXT_PUBLIC_NETWORK_ICON=https://example.com/icon.png
+NEXT_PUBLIC_NETWORK_ICON_DARK=https://example.com/icon.png
+NEXT_PUBLIC_NETWORK_LOGO=https://example.com/logo.png
+NEXT_PUBLIC_NETWORK_LOGO_DARK=https://example.com/logo.png
+NEXT_PUBLIC_NETWORK_RPC_URL=https://example.com
+NEXT_PUBLIC_NETWORK_SHORT_NAME=Test
+NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation
+NEXT_PUBLIC_OG_DESCRIPTION='Hello world!'
+NEXT_PUBLIC_OG_IMAGE_URL=https://example.com/image.png
+NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_SEO_ENHANCED_DATA_ENABLED=true
+NEXT_PUBLIC_OTHER_LINKS=[{'url':'https://blockscout.com','text':'Blockscout'}]
+NEXT_PUBLIC_PROMOTE_BLOCKSCOUT_IN_TITLE=true
+NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-mainnet.safe.global
+NEXT_PUBLIC_STATS_API_HOST=https://example.com
+NEXT_PUBLIC_STATS_API_BASE_PATH=/
+NEXT_PUBLIC_USE_NEXT_JS_PROXY=false
+NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE=gradient_avatar
+NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT=['base16']
+NEXT_PUBLIC_VIEWS_ADDRESS_HIDDEN_VIEWS=['top_accounts']
+NEXT_PUBLIC_VIEWS_CONTRACT_EXTRA_VERIFICATION_METHODS=['solidity-hardhat','solidity-foundry']
+NEXT_PUBLIC_VIEWS_CONTRACT_LANGUAGE_FILTERS=['solidity','vyper','yul','scilla']
+NEXT_PUBLIC_VIEWS_BLOCK_HIDDEN_FIELDS=['burnt_fees','total_reward']
+NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES=[{'name':'NFT Marketplace','collection_url':'https://example.com/{hash}','instance_url':'https://example.com/{hash}/{id}','logo_url':'https://example.com/logo.png'}]
+NEXT_PUBLIC_VIEWS_TX_ADDITIONAL_FIELDS=['fee_per_gas']
+NEXT_PUBLIC_VIEWS_TX_HIDDEN_FIELDS=['value','fee_currency','gas_price','tx_fee','gas_fees','burnt_fees']
+NEXT_PUBLIC_VISUALIZE_API_HOST=https://example.com
+NEXT_PUBLIC_VISUALIZE_API_BASE_PATH=https://example.com
+NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET=false
+NEXT_PUBLIC_WEB3_WALLETS=['coinbase','metamask','token_pocket']
+NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE=stability
+NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swap','icon':'swap','dappId':'uniswap'},{'text':'Payment link','icon':'payment_link','url':'https://example.com'}]
+NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}]
+NEXT_PUBLIC_GAS_REFUEL_PROVIDER_CONFIG={'name': 'Need gas?', 'dapp_id': 'smol-refuel', 'url_template': 'https://smolrefuel.com/?outboundChain={chainId}&partner=blockscout&utm_source=blockscout&utm_medium=address&disableBridges=true', 'logo': 'https://blockscout-content.s3.amazonaws.com/smolrefuel-logo-action-button.png'}
+NEXT_PUBLIC_SAVE_ON_GAS_ENABLED=true
+NEXT_PUBLIC_REWARDS_SERVICE_API_HOST=https://example.com
diff --git a/explorer/frontend/deploy/tools/envs-validator/test/.env.beacon_chain b/explorer/frontend/deploy/tools/envs-validator/test/.env.beacon_chain
new file mode 100644
index 000000000..f0800e9af
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/test/.env.beacon_chain
@@ -0,0 +1,2 @@
+NEXT_PUBLIC_HAS_BEACON_CHAIN=true
+NEXT_PUBLIC_BEACON_CHAIN_CURRENCY_SYMBOL=aETH
\ No newline at end of file
diff --git a/explorer/frontend/deploy/tools/envs-validator/test/.env.celo b/explorer/frontend/deploy/tools/envs-validator/test/.env.celo
new file mode 100644
index 000000000..108204420
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/test/.env.celo
@@ -0,0 +1,2 @@
+NEXT_PUBLIC_CELO_ENABLED=true
+NEXT_PUBLIC_CELO_L2_UPGRADE_BLOCK=420
\ No newline at end of file
diff --git a/explorer/frontend/deploy/tools/envs-validator/test/.env.common b/explorer/frontend/deploy/tools/envs-validator/test/.env.common
new file mode 100644
index 000000000..5788f392d
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/test/.env.common
@@ -0,0 +1,4 @@
+NEXT_PUBLIC_API_HOST=blockscout.com
+NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_NETWORK_ID=1
+NEXT_PUBLIC_NETWORK_NAME=Testnet
diff --git a/explorer/frontend/deploy/tools/envs-validator/test/.env.external_txs b/explorer/frontend/deploy/tools/envs-validator/test/.env.external_txs
new file mode 100644
index 000000000..97129b0e6
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/test/.env.external_txs
@@ -0,0 +1 @@
+NEXT_PUBLIC_TX_EXTERNAL_TRANSACTIONS_CONFIG={'chain_name':'Solana','chain_logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/refs/heads/main/configs/network-icons/solana.svg','explorer_url_template':'https://solscan.io/tx/{hash}'}
\ No newline at end of file
diff --git a/explorer/frontend/deploy/tools/envs-validator/test/.env.marketplace b/explorer/frontend/deploy/tools/envs-validator/test/.env.marketplace
new file mode 100644
index 000000000..6cc6b1f83
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/test/.env.marketplace
@@ -0,0 +1,12 @@
+NEXT_PUBLIC_MARKETPLACE_ENABLED=true
+NEXT_PUBLIC_MARKETPLACE_CONFIG_URL=https://example.com
+NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://example.com
+NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://example.com
+NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://example.com
+NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL=https://example.com
+NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://example.com
+NEXT_PUBLIC_MARKETPLACE_FEATURED_APP=aave
+NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL=https://gist.githubusercontent.com/maxaleks/36f779fd7d74877b57ec7a25a9a3a6c9/raw/746a8a59454c0537235ee44616c4690ce3bbf3c8/banner.html
+NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL=https://www.basename.app
+NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_API_KEY=test
+NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID=test
diff --git a/explorer/frontend/deploy/tools/envs-validator/test/.env.optimism b/explorer/frontend/deploy/tools/envs-validator/test/.env.optimism
new file mode 100644
index 000000000..32d36f397
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/test/.env.optimism
@@ -0,0 +1,8 @@
+NEXT_PUBLIC_ROLLUP_TYPE=optimistic
+NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://example.com
+NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL=https://example.com
+NEXT_PUBLIC_FAULT_PROOF_ENABLED=true
+NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS=true
+NEXT_PUBLIC_ROLLUP_OUTPUT_ROOTS_ENABLED=false
+NEXT_PUBLIC_ROLLUP_PARENT_CHAIN={'baseUrl':'https://explorer.duckchain.io'}
+NEXT_PUBLIC_INTEROP_ENABLED=true
\ No newline at end of file
diff --git a/explorer/frontend/deploy/tools/envs-validator/test/assets/configs/featured_networks.json b/explorer/frontend/deploy/tools/envs-validator/test/assets/configs/featured_networks.json
new file mode 100644
index 000000000..83b908884
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/test/assets/configs/featured_networks.json
@@ -0,0 +1,22 @@
+[
+ {
+ "title": "Ethereum",
+ "url": "https://eth.blockscout.com/",
+ "group": "Mainnets",
+ "icon": "https://example.com/logo.svg"
+ },
+ {
+ "title": "Goerli",
+ "url": "https://eth-goerli.blockscout.com/",
+ "group": "Testnets",
+ "isActive": true,
+ "icon": "https://example.com/logo.svg",
+ "invertIconInDarkMode": true
+ },
+ {
+ "title": "POA Sokol",
+ "url": "https://blockscout.com/poa/sokol",
+ "group": "Other",
+ "icon": "https://example.com/logo.svg"
+ }
+]
\ No newline at end of file
diff --git a/explorer/frontend/deploy/tools/envs-validator/test/assets/configs/footer_links.json b/explorer/frontend/deploy/tools/envs-validator/test/assets/configs/footer_links.json
new file mode 100644
index 000000000..d3f7e7d43
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/test/assets/configs/footer_links.json
@@ -0,0 +1,28 @@
+[
+ {
+ "title": "Foo",
+ "links": [
+ {
+ "text": "Home",
+ "url": "https://example.com"
+ },
+ {
+ "text": "Brand",
+ "url": "https://example.com"
+ }
+ ]
+ },
+ {
+ "title": "Developers",
+ "links": [
+ {
+ "text": "Develop",
+ "url": "https://example.com"
+ },
+ {
+ "text": "Grants",
+ "url": "https://example.com"
+ }
+ ]
+ }
+ ]
\ No newline at end of file
diff --git a/explorer/frontend/deploy/tools/envs-validator/test/assets/configs/marketplace_categories.json b/explorer/frontend/deploy/tools/envs-validator/test/assets/configs/marketplace_categories.json
new file mode 100644
index 000000000..15b31a555
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/test/assets/configs/marketplace_categories.json
@@ -0,0 +1,5 @@
+[
+ "Swaps",
+ "Bridges",
+ "NFT"
+]
diff --git a/explorer/frontend/deploy/tools/envs-validator/test/assets/configs/marketplace_config.json b/explorer/frontend/deploy/tools/envs-validator/test/assets/configs/marketplace_config.json
new file mode 100644
index 000000000..0b142b7a2
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/test/assets/configs/marketplace_config.json
@@ -0,0 +1,25 @@
+[
+ {
+ "author": "Hop",
+ "id": "hop-exchange",
+ "title": "Hop",
+ "logo": "https://example.com/logo.svg",
+ "categories": ["Bridge"],
+ "shortDescription": "Hop is a scalable rollup-to-rollup general token bridge.",
+ "site": "https://example.com",
+ "description": "Hop is a scalable rollup-to-rollup general token bridge.",
+ "external": true,
+ "url": "https://example.com"
+ },
+ {
+ "author": "Blockscout",
+ "id": "token-approval-tracker",
+ "title": "Token Approval Tracker",
+ "logo": "https://example.com/logo.svg",
+ "categories": ["Infra & Dev tooling"],
+ "shortDescription": "Token Approval Tracker shows all approvals for any ERC20-compliant tokens and NFTs and lets to revoke them or adjust the approved amount.",
+ "site": "https://example.com",
+ "description": "Token Approval Tracker shows all approvals for any ERC20-compliant tokens and NFTs and lets to revoke them or adjust the approved amount.",
+ "url": "https://example.com"
+ }
+ ]
diff --git a/explorer/frontend/deploy/tools/envs-validator/test/assets/configs/marketplace_security_reports.json b/explorer/frontend/deploy/tools/envs-validator/test/assets/configs/marketplace_security_reports.json
new file mode 100644
index 000000000..cf0f481ae
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/test/assets/configs/marketplace_security_reports.json
@@ -0,0 +1,1073 @@
+[
+ {
+ "appName": "paraswap",
+ "doc": "https://developers.paraswap.network/smart-contracts",
+ "chainsData": {
+ "1": {
+ "overallInfo": {
+ "verifiedNumber": 4,
+ "totalContractsNumber": 4,
+ "solidityScanContractsNumber": 4,
+ "securityScore": 77.41749999999999,
+ "issueSeverityDistribution": {
+ "critical": 5,
+ "gas": 58,
+ "high": 9,
+ "informational": 27,
+ "low": 41,
+ "medium": 5
+ }
+ },
+ "contractsData": [
+ {
+ "address": "0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57",
+ "contract_chain": "optimism",
+ "contract_platform": "blockscout",
+ "contract_url": "https://optimism.blockscout.com/address/0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57",
+ "contractname": "AugustusSwapper",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57/blockscout/eth?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 8,
+ "high": 4,
+ "informational": 7,
+ "low": 8,
+ "medium": 1
+ },
+ "lines_analyzed_count": 180,
+ "scan_time_taken": 1,
+ "score": "3.61",
+ "score_v2": "72.22",
+ "threat_score": "73.68"
+ }
+ }
+ },
+ {
+ "address": "0x216b4b4ba9f3e719726886d34a177484278bfcae",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0x216b4b4ba9f3e719726886d34a177484278bfcae",
+ "contract_chain": "eth",
+ "contract_platform": "blockscout",
+ "contract_url": "https://eth.blockscout.com/address/0x216b4b4ba9f3e719726886d34a177484278bfcae",
+ "contractname": "TokenTransferProxy",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0x216b4b4ba9f3e719726886d34a177484278bfcae/blockscout/eth?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 1,
+ "gas": 29,
+ "high": 5,
+ "informational": 14,
+ "low": 21,
+ "medium": 3
+ },
+ "lines_analyzed_count": 553,
+ "scan_time_taken": 1,
+ "score": "3.92",
+ "score_v2": "78.48",
+ "threat_score": "78.95"
+ }
+ }
+ },
+ {
+ "address": "0xa68bEA62Dc4034A689AA0F58A76681433caCa663",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0xa68bEA62Dc4034A689AA0F58A76681433caCa663",
+ "contract_chain": "eth",
+ "contract_platform": "blockscout",
+ "contract_url": "https://eth.blockscout.com/address/0xa68bEA62Dc4034A689AA0F58A76681433caCa663",
+ "contractname": "AugustusRegistry",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0xa68bEA62Dc4034A689AA0F58A76681433caCa663/blockscout/eth?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 3,
+ "high": 0,
+ "informational": 5,
+ "low": 4,
+ "medium": 0
+ },
+ "lines_analyzed_count": 103,
+ "scan_time_taken": 0,
+ "score": "4.22",
+ "score_v2": "84.47",
+ "threat_score": "88.89"
+ }
+ }
+ },
+ {
+ "address": "0xeF13101C5bbD737cFb2bF00Bbd38c626AD6952F7",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0xeF13101C5bbD737cFb2bF00Bbd38c626AD6952F7",
+ "contract_chain": "eth",
+ "contract_platform": "blockscout",
+ "contract_url": "https://eth.blockscout.com/address/0xeF13101C5bbD737cFb2bF00Bbd38c626AD6952F7",
+ "contractname": "FeeClaimer",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0xeF13101C5bbD737cFb2bF00Bbd38c626AD6952F7/blockscout/eth?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 18,
+ "high": 0,
+ "informational": 1,
+ "low": 8,
+ "medium": 1
+ },
+ "lines_analyzed_count": 149,
+ "scan_time_taken": 0,
+ "score": "3.72",
+ "score_v2": "74.50",
+ "threat_score": "94.74"
+ }
+ }
+ }
+ ]
+ },
+ "10": {
+ "overallInfo": {
+ "verifiedNumber": 3,
+ "totalContractsNumber": 4,
+ "solidityScanContractsNumber": 3,
+ "securityScore": 75.44333333333333,
+ "issueSeverityDistribution": {
+ "critical": 4,
+ "gas": 29,
+ "high": 4,
+ "informational": 20,
+ "low": 20,
+ "medium": 2
+ }
+ },
+ "contractsData": [
+ {
+ "address": "0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57",
+ "contract_chain": "optimism",
+ "contract_platform": "blockscout",
+ "contract_url": "https://optimism.blockscout.com/address/0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57",
+ "contractname": "AugustusSwapper",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57/blockscout/optimism?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 8,
+ "high": 4,
+ "informational": 7,
+ "low": 8,
+ "medium": 1
+ },
+ "lines_analyzed_count": 180,
+ "scan_time_taken": 1,
+ "score": "3.61",
+ "score_v2": "72.22",
+ "threat_score": "73.68"
+ }
+ }
+ },
+ {
+ "address": "0x216B4B4Ba9F3e719726886d34a177484278Bfcae",
+ "isVerified": false,
+ "solidityScanReport": null
+ },
+ {
+ "address": "0x6e7bE86000dF697facF4396efD2aE2C322165dC3",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0x6e7bE86000dF697facF4396efD2aE2C322165dC3",
+ "contract_chain": "optimism",
+ "contract_platform": "blockscout",
+ "contract_url": "https://optimism.blockscout.com/address/0x6e7bE86000dF697facF4396efD2aE2C322165dC3",
+ "contractname": "AugustusRegistry",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0x6e7bE86000dF697facF4396efD2aE2C322165dC3/blockscout/optimism?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 3,
+ "high": 0,
+ "informational": 5,
+ "low": 4,
+ "medium": 0
+ },
+ "lines_analyzed_count": 102,
+ "scan_time_taken": 0,
+ "score": "4.22",
+ "score_v2": "84.31",
+ "threat_score": "88.89"
+ }
+ }
+ },
+ {
+ "address": "0xA7465CCD97899edcf11C56D2d26B49125674e45F",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0xA7465CCD97899edcf11C56D2d26B49125674e45F",
+ "contract_chain": "optimism",
+ "contract_platform": "blockscout",
+ "contract_url": "https://optimism.blockscout.com/address/0xA7465CCD97899edcf11C56D2d26B49125674e45F",
+ "contractname": "FeeClaimer",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0xA7465CCD97899edcf11C56D2d26B49125674e45F/blockscout/optimism?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 18,
+ "high": 0,
+ "informational": 8,
+ "low": 8,
+ "medium": 1
+ },
+ "lines_analyzed_count": 149,
+ "scan_time_taken": 1,
+ "score": "3.49",
+ "score_v2": "69.80",
+ "threat_score": "94.74"
+ }
+ }
+ }
+ ]
+ },
+ "8453": {
+ "overallInfo": {
+ "verifiedNumber": 1,
+ "totalContractsNumber": 4,
+ "solidityScanContractsNumber": 1,
+ "securityScore": 73.33,
+ "issueSeverityDistribution": {
+ "critical": 4,
+ "gas": 8,
+ "high": 4,
+ "informational": 5,
+ "low": 8,
+ "medium": 1
+ }
+ },
+ "contractsData": [
+ {
+ "address": "0x59C7C832e96D2568bea6db468C1aAdcbbDa08A52",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0x59C7C832e96D2568bea6db468C1aAdcbbDa08A52",
+ "contract_chain": "base",
+ "contract_platform": "blockscout",
+ "contract_url": "https://base.blockscout.com/address/0x59C7C832e96D2568bea6db468C1aAdcbbDa08A52",
+ "contractname": "AugustusSwapper",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0x59C7C832e96D2568bea6db468C1aAdcbbDa08A52/blockscout/base?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 8,
+ "high": 4,
+ "informational": 5,
+ "low": 8,
+ "medium": 1
+ },
+ "lines_analyzed_count": 180,
+ "scan_time_taken": 1,
+ "score": "3.67",
+ "score_v2": "73.33",
+ "threat_score": "73.68"
+ }
+ }
+ },
+ {
+ "address": "0x93aAAe79a53759cD164340E4C8766E4Db5331cD7",
+ "isVerified": false,
+ "solidityScanReport": null
+ },
+ {
+ "address": "0x7e31b336f9e8ba52ba3c4ac861b033ba90900bb3",
+ "isVerified": false,
+ "solidityScanReport": null
+ },
+ {
+ "address": "0x9aaB4B24541af30fD72784ED98D8756ac0eFb3C7",
+ "isVerified": false,
+ "solidityScanReport": null
+ }
+ ]
+ }
+ }
+ },
+ {
+ "appName": "mean-finance",
+ "doc": "https://docs.mean.finance/guides/smart-contract-registry",
+ "chainsData": {
+ "1": {
+ "overallInfo": {
+ "verifiedNumber": 4,
+ "totalContractsNumber": 6,
+ "solidityScanContractsNumber": 4,
+ "securityScore": 61.36750000000001,
+ "issueSeverityDistribution": {
+ "critical": 6,
+ "gas": 25,
+ "high": 1,
+ "informational": 10,
+ "low": 20,
+ "medium": 3
+ }
+ },
+ "contractsData": [
+ {
+ "address": "0xA5AdC5484f9997fBF7D405b9AA62A7d88883C345",
+ "isVerified": false,
+ "solidityScanReport": null
+ },
+ {
+ "address": "0x20bdAE1413659f47416f769a4B27044946bc9923",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0x20bdAE1413659f47416f769a4B27044946bc9923",
+ "contract_chain": "optimism",
+ "contract_platform": "blockscout",
+ "contract_url": "https://optimism.blockscout.com/address/0x20bdAE1413659f47416f769a4B27044946bc9923",
+ "contractname": "DCAPermissionsManager",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0x20bdAE1413659f47416f769a4B27044946bc9923/blockscout/eth?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 2,
+ "gas": 22,
+ "high": 0,
+ "informational": 8,
+ "low": 11,
+ "medium": 3
+ },
+ "lines_analyzed_count": 314,
+ "scan_time_taken": 1,
+ "score": "3.87",
+ "score_v2": "77.39",
+ "threat_score": "88.89"
+ }
+ }
+ },
+ {
+ "address": "0xDf0dbc66f85979a1d54671c4D9e439F306Be27EE",
+ "isVerified": false,
+ "solidityScanReport": null
+ },
+ {
+ "address": "0x4ACd4BC402bc8e6BA8aBDdcA639d8011ef0b8a4b",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0x4ACd4BC402bc8e6BA8aBDdcA639d8011ef0b8a4b",
+ "contract_chain": "eth",
+ "contract_platform": "blockscout",
+ "contract_url": "https://eth.blockscout.com/address/0x4ACd4BC402bc8e6BA8aBDdcA639d8011ef0b8a4b",
+ "contractname": "DCAHubPositionDescriptor",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0x4ACd4BC402bc8e6BA8aBDdcA639d8011ef0b8a4b/blockscout/eth?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 1,
+ "high": 1,
+ "informational": 2,
+ "low": 3,
+ "medium": 0
+ },
+ "lines_analyzed_count": 280,
+ "scan_time_taken": 1,
+ "score": "4.77",
+ "score_v2": "95.36",
+ "threat_score": "100.00"
+ }
+ }
+ },
+ {
+ "address": "0x49c590F6a2dfB0f809E82B9e2BF788C0Dd1c31f9",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0x49c590F6a2dfB0f809E82B9e2BF788C0Dd1c31f9",
+ "contract_chain": "eth",
+ "contract_platform": "blockscout",
+ "contract_url": "https://eth.blockscout.com/address/0x49c590F6a2dfB0f809E82B9e2BF788C0Dd1c31f9",
+ "contractname": "DCAHubCompanion",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0x49c590F6a2dfB0f809E82B9e2BF788C0Dd1c31f9/blockscout/eth?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 1,
+ "high": 0,
+ "informational": 0,
+ "low": 3,
+ "medium": 0
+ },
+ "lines_analyzed_count": 11,
+ "scan_time_taken": 0,
+ "score": "1.82",
+ "score_v2": "36.36",
+ "threat_score": "100.00"
+ }
+ }
+ },
+ {
+ "address": "0x5ad2fED59E8DF461c6164c31B4267Efb7cBaF9C0",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0x5ad2fED59E8DF461c6164c31B4267Efb7cBaF9C0",
+ "contract_chain": "eth",
+ "contract_platform": "blockscout",
+ "contract_url": "https://eth.blockscout.com/address/0x5ad2fED59E8DF461c6164c31B4267Efb7cBaF9C0",
+ "contractname": "DCAHubCompanion",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0x5ad2fED59E8DF461c6164c31B4267Efb7cBaF9C0/blockscout/eth?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 1,
+ "high": 0,
+ "informational": 0,
+ "low": 3,
+ "medium": 0
+ },
+ "lines_analyzed_count": 11,
+ "scan_time_taken": 0,
+ "score": "1.82",
+ "score_v2": "36.36",
+ "threat_score": "100.00"
+ }
+ }
+ }
+ ]
+ },
+ "10": {
+ "overallInfo": {
+ "verifiedNumber": 5,
+ "totalContractsNumber": 6,
+ "solidityScanContractsNumber": 5,
+ "securityScore": 66.986,
+ "issueSeverityDistribution": {
+ "critical": 6,
+ "gas": 26,
+ "high": 1,
+ "informational": 10,
+ "low": 23,
+ "medium": 3
+ }
+ },
+ "contractsData": [
+ {
+ "address": "0xA5AdC5484f9997fBF7D405b9AA62A7d88883C345",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0xA5AdC5484f9997fBF7D405b9AA62A7d88883C345",
+ "contract_chain": "optimism",
+ "contract_platform": "blockscout",
+ "contract_url": "https://optimism.blockscout.com/address/0xA5AdC5484f9997fBF7D405b9AA62A7d88883C345",
+ "contractname": "DCAHub",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0xA5AdC5484f9997fBF7D405b9AA62A7d88883C345/blockscout/optimism?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 1,
+ "high": 0,
+ "informational": 0,
+ "low": 3,
+ "medium": 0
+ },
+ "lines_analyzed_count": 23,
+ "scan_time_taken": 0,
+ "score": "3.48",
+ "score_v2": "69.57",
+ "threat_score": "94.44"
+ }
+ }
+ },
+ {
+ "address": "0x20bdAE1413659f47416f769a4B27044946bc9923",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0x20bdAE1413659f47416f769a4B27044946bc9923",
+ "contract_chain": "optimism",
+ "contract_platform": "blockscout",
+ "contract_url": "https://optimism.blockscout.com/address/0x20bdAE1413659f47416f769a4B27044946bc9923",
+ "contractname": "DCAPermissionsManager",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0x20bdAE1413659f47416f769a4B27044946bc9923/blockscout/optimism?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 2,
+ "gas": 22,
+ "high": 0,
+ "informational": 8,
+ "low": 11,
+ "medium": 3
+ },
+ "lines_analyzed_count": 314,
+ "scan_time_taken": 1,
+ "score": "3.87",
+ "score_v2": "77.39",
+ "threat_score": "88.89"
+ }
+ }
+ },
+ {
+ "address": "0xDf0dbc66f85979a1d54671c4D9e439F306Be27EE",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0xDf0dbc66f85979a1d54671c4D9e439F306Be27EE",
+ "contract_chain": "optimism",
+ "contract_platform": "blockscout",
+ "contract_url": "https://optimism.blockscout.com/address/0xDf0dbc66f85979a1d54671c4D9e439F306Be27EE",
+ "contractname": "DCAHubCompanion",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0xDf0dbc66f85979a1d54671c4D9e439F306Be27EE/blockscout/optimism?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 1,
+ "high": 0,
+ "informational": 0,
+ "low": 3,
+ "medium": 0
+ },
+ "lines_analyzed_count": 16,
+ "scan_time_taken": 0,
+ "score": "2.81",
+ "score_v2": "56.25",
+ "threat_score": "100.00"
+ }
+ }
+ },
+ {
+ "address": "0x4ACd4BC402bc8e6BA8aBDdcA639d8011ef0b8a4b",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0x4ACd4BC402bc8e6BA8aBDdcA639d8011ef0b8a4b",
+ "contract_chain": "eth",
+ "contract_platform": "blockscout",
+ "contract_url": "https://eth.blockscout.com/address/0x4ACd4BC402bc8e6BA8aBDdcA639d8011ef0b8a4b",
+ "contractname": "DCAHubPositionDescriptor",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0x4ACd4BC402bc8e6BA8aBDdcA639d8011ef0b8a4b/blockscout/optimism?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 1,
+ "high": 1,
+ "informational": 2,
+ "low": 3,
+ "medium": 0
+ },
+ "lines_analyzed_count": 280,
+ "scan_time_taken": 1,
+ "score": "4.77",
+ "score_v2": "95.36",
+ "threat_score": "100.00"
+ }
+ }
+ },
+ {
+ "address": "0x49c590F6a2dfB0f809E82B9e2BF788C0Dd1c31f9",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0x49c590F6a2dfB0f809E82B9e2BF788C0Dd1c31f9",
+ "contract_chain": "optimism",
+ "contract_platform": "blockscout",
+ "contract_url": "https://optimism.blockscout.com/address/0x49c590F6a2dfB0f809E82B9e2BF788C0Dd1c31f9",
+ "contractname": "DCAHubCompanion",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0x49c590F6a2dfB0f809E82B9e2BF788C0Dd1c31f9/blockscout/optimism?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 1,
+ "high": 0,
+ "informational": 0,
+ "low": 3,
+ "medium": 0
+ },
+ "lines_analyzed_count": 11,
+ "scan_time_taken": 0,
+ "score": "1.82",
+ "score_v2": "36.36",
+ "threat_score": "100.00"
+ }
+ }
+ },
+ {
+ "address": "0x5ad2fED59E8DF461c6164c31B4267Efb7cBaF9C0",
+ "isVerified": false,
+ "solidityScanReport": null
+ }
+ ]
+ },
+ "8453": {
+ "overallInfo": {
+ "verifiedNumber": 4,
+ "totalContractsNumber": 6,
+ "solidityScanContractsNumber": 4,
+ "securityScore": 74.88,
+ "issueSeverityDistribution": {
+ "critical": 6,
+ "gas": 25,
+ "high": 1,
+ "informational": 7,
+ "low": 20,
+ "medium": 3
+ }
+ },
+ "contractsData": [
+ {
+ "address": "0xA5AdC5484f9997fBF7D405b9AA62A7d88883C345",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0xA5AdC5484f9997fBF7D405b9AA62A7d88883C345",
+ "contract_chain": "base",
+ "contract_platform": "blockscout",
+ "contract_url": "https://base.blockscout.com/address/0xA5AdC5484f9997fBF7D405b9AA62A7d88883C345",
+ "contractname": "DCAHub",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0xA5AdC5484f9997fBF7D405b9AA62A7d88883C345/blockscout/base?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 1,
+ "high": 0,
+ "informational": 0,
+ "low": 3,
+ "medium": 0
+ },
+ "lines_analyzed_count": 23,
+ "scan_time_taken": 0,
+ "score": "3.48",
+ "score_v2": "69.57",
+ "threat_score": "94.44"
+ }
+ }
+ },
+ {
+ "address": "0x20bdAE1413659f47416f769a4B27044946bc9923",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0x20bdAE1413659f47416f769a4B27044946bc9923",
+ "contract_chain": "base",
+ "contract_platform": "blockscout",
+ "contract_url": "https://base.blockscout.com/address/0x20bdAE1413659f47416f769a4B27044946bc9923",
+ "contractname": "DCAPermissionsManager",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0x20bdAE1413659f47416f769a4B27044946bc9923/blockscout/base?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 2,
+ "gas": 22,
+ "high": 0,
+ "informational": 5,
+ "low": 11,
+ "medium": 3
+ },
+ "lines_analyzed_count": 314,
+ "scan_time_taken": 1,
+ "score": "3.92",
+ "score_v2": "78.34",
+ "threat_score": "88.89"
+ }
+ }
+ },
+ {
+ "address": "0xDf0dbc66f85979a1d54671c4D9e439F306Be27EE",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0xDf0dbc66f85979a1d54671c4D9e439F306Be27EE",
+ "contract_chain": "base",
+ "contract_platform": "blockscout",
+ "contract_url": "https://base.blockscout.com/address/0xDf0dbc66f85979a1d54671c4D9e439F306Be27EE",
+ "contractname": "DCAHubCompanion",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0xDf0dbc66f85979a1d54671c4D9e439F306Be27EE/blockscout/base?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 1,
+ "high": 0,
+ "informational": 0,
+ "low": 3,
+ "medium": 0
+ },
+ "lines_analyzed_count": 16,
+ "scan_time_taken": 0,
+ "score": "2.81",
+ "score_v2": "56.25",
+ "threat_score": "100.00"
+ }
+ }
+ },
+ {
+ "address": "0x4ACd4BC402bc8e6BA8aBDdcA639d8011ef0b8a4b",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0x4ACd4BC402bc8e6BA8aBDdcA639d8011ef0b8a4b",
+ "contract_chain": "eth",
+ "contract_platform": "blockscout",
+ "contract_url": "https://eth.blockscout.com/address/0x4ACd4BC402bc8e6BA8aBDdcA639d8011ef0b8a4b",
+ "contractname": "DCAHubPositionDescriptor",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0x4ACd4BC402bc8e6BA8aBDdcA639d8011ef0b8a4b/blockscout/base?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 1,
+ "high": 1,
+ "informational": 2,
+ "low": 3,
+ "medium": 0
+ },
+ "lines_analyzed_count": 280,
+ "scan_time_taken": 1,
+ "score": "4.77",
+ "score_v2": "95.36",
+ "threat_score": "100.00"
+ }
+ }
+ },
+ {
+ "address": "0x49c590F6a2dfB0f809E82B9e2BF788C0Dd1c31f9",
+ "isVerified": false,
+ "solidityScanReport": null
+ },
+ {
+ "address": "0x5ad2fED59E8DF461c6164c31B4267Efb7cBaF9C0",
+ "isVerified": false,
+ "solidityScanReport": null
+ }
+ ]
+ }
+ }
+ },
+ {
+ "appName": "cow-swap",
+ "doc": "https://docs.cow.fi/cow-protocol/reference/contracts/core#deployments",
+ "chainsData": {
+ "1": {
+ "overallInfo": {
+ "verifiedNumber": 3,
+ "totalContractsNumber": 3,
+ "solidityScanContractsNumber": 3,
+ "securityScore": 87.60000000000001,
+ "issueSeverityDistribution": {
+ "critical": 4,
+ "gas": 18,
+ "high": 0,
+ "informational": 13,
+ "low": 14,
+ "medium": 3
+ }
+ },
+ "contractsData": [
+ {
+ "address": "0x9008D19f58AAbD9eD0D60971565AA8510560ab41",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0x9008D19f58AAbD9eD0D60971565AA8510560ab41",
+ "contract_chain": "eth",
+ "contract_platform": "blockscout",
+ "contract_url": "https://eth.blockscout.com/address/0x9008D19f58AAbD9eD0D60971565AA8510560ab41",
+ "contractname": "GPv2Settlement",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0x9008D19f58AAbD9eD0D60971565AA8510560ab41/blockscout/eth?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 16,
+ "high": 0,
+ "informational": 7,
+ "low": 5,
+ "medium": 3
+ },
+ "lines_analyzed_count": 493,
+ "scan_time_taken": 1,
+ "score": "4.57",
+ "score_v2": "91.48",
+ "threat_score": "94.74"
+ }
+ }
+ },
+ {
+ "address": "0x2c4c28DDBdAc9C5E7055b4C863b72eA0149D8aFE",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0x2c4c28DDBdAc9C5E7055b4C863b72eA0149D8aFE",
+ "contract_chain": "eth",
+ "contract_platform": "blockscout",
+ "contract_url": "https://eth.blockscout.com/address/0x2c4c28DDBdAc9C5E7055b4C863b72eA0149D8aFE",
+ "contractname": "EIP173Proxy",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0x2c4c28DDBdAc9C5E7055b4C863b72eA0149D8aFE/blockscout/eth?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 0,
+ "high": 0,
+ "informational": 4,
+ "low": 5,
+ "medium": 0
+ },
+ "lines_analyzed_count": 94,
+ "scan_time_taken": 0,
+ "score": "4.26",
+ "score_v2": "85.11",
+ "threat_score": "88.89"
+ }
+ }
+ },
+ {
+ "address": "0xC92E8bdf79f0507f65a392b0ab4667716BFE0110",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0xC92E8bdf79f0507f65a392b0ab4667716BFE0110",
+ "contract_chain": "eth",
+ "contract_platform": "blockscout",
+ "contract_url": "https://eth.blockscout.com/address/0xC92E8bdf79f0507f65a392b0ab4667716BFE0110",
+ "contractname": "GPv2VaultRelayer",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0xC92E8bdf79f0507f65a392b0ab4667716BFE0110/blockscout/eth?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 2,
+ "high": 0,
+ "informational": 2,
+ "low": 4,
+ "medium": 0
+ },
+ "lines_analyzed_count": 87,
+ "scan_time_taken": 0,
+ "score": "4.31",
+ "score_v2": "86.21",
+ "threat_score": "94.74"
+ }
+ }
+ }
+ ]
+ },
+ "100": {
+ "overallInfo": {
+ "verifiedNumber": 3,
+ "totalContractsNumber": 3,
+ "solidityScanContractsNumber": 3,
+ "securityScore": 87.60000000000001,
+ "issueSeverityDistribution": {
+ "critical": 4,
+ "gas": 18,
+ "high": 0,
+ "informational": 13,
+ "low": 14,
+ "medium": 3
+ }
+ },
+ "contractsData": [
+ {
+ "address": "0x9008D19f58AAbD9eD0D60971565AA8510560ab41",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0x9008D19f58AAbD9eD0D60971565AA8510560ab41",
+ "contract_chain": "gnosis",
+ "contract_platform": "blockscout",
+ "contract_url": "https://gnosis.blockscout.com/address/0x9008D19f58AAbD9eD0D60971565AA8510560ab41",
+ "contractname": "GPv2Settlement",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0x9008D19f58AAbD9eD0D60971565AA8510560ab41/blockscout/gnosis?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 16,
+ "high": 0,
+ "informational": 7,
+ "low": 5,
+ "medium": 3
+ },
+ "lines_analyzed_count": 493,
+ "scan_time_taken": 1,
+ "score": "4.57",
+ "score_v2": "91.48",
+ "threat_score": "94.74"
+ }
+ }
+ },
+ {
+ "address": "0x2c4c28DDBdAc9C5E7055b4C863b72eA0149D8aFE",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0x2c4c28DDBdAc9C5E7055b4C863b72eA0149D8aFE",
+ "contract_chain": "eth",
+ "contract_platform": "blockscout",
+ "contract_url": "https://eth.blockscout.com/address/0x2c4c28DDBdAc9C5E7055b4C863b72eA0149D8aFE",
+ "contractname": "EIP173Proxy",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0x2c4c28DDBdAc9C5E7055b4C863b72eA0149D8aFE/blockscout/gnosis?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 0,
+ "high": 0,
+ "informational": 4,
+ "low": 5,
+ "medium": 0
+ },
+ "lines_analyzed_count": 94,
+ "scan_time_taken": 0,
+ "score": "4.26",
+ "score_v2": "85.11",
+ "threat_score": "88.89"
+ }
+ }
+ },
+ {
+ "address": "0xC92E8bdf79f0507f65a392b0ab4667716BFE0110",
+ "isVerified": true,
+ "solidityScanReport": {
+ "connection_id": "",
+ "contract_address": "0xC92E8bdf79f0507f65a392b0ab4667716BFE0110",
+ "contract_chain": "eth",
+ "contract_platform": "blockscout",
+ "contract_url": "https://eth.blockscout.com/address/0xC92E8bdf79f0507f65a392b0ab4667716BFE0110",
+ "contractname": "GPv2VaultRelayer",
+ "is_quick_scan": true,
+ "node_reference_id": null,
+ "request_type": "threat_scan",
+ "scanner_reference_url": "https://solidityscan.com/quickscan/0xC92E8bdf79f0507f65a392b0ab4667716BFE0110/blockscout/gnosis?ref=blockscout",
+ "scan_status": "scan_done",
+ "scan_summary": {
+ "issue_severity_distribution": {
+ "critical": 0,
+ "gas": 2,
+ "high": 0,
+ "informational": 2,
+ "low": 4,
+ "medium": 0
+ },
+ "lines_analyzed_count": 87,
+ "scan_time_taken": 0,
+ "score": "4.31",
+ "score_v2": "86.21",
+ "threat_score": "94.74"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+]
diff --git a/explorer/frontend/deploy/tools/envs-validator/tsconfig.json b/explorer/frontend/deploy/tools/envs-validator/tsconfig.json
new file mode 100644
index 000000000..f7911a9e1
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/tsconfig.json
@@ -0,0 +1,24 @@
+{
+ "extends": "../../../tsconfig.json",
+ "compilerOptions": {
+ "noEmit": false,
+ "target": "es2016",
+ "module": "CommonJS",
+ "moduleResolution": "node",
+ "paths": {
+ "nextjs-routes": ["./nextjs/nextjs-routes.d.ts"],
+ }
+ },
+ "include": [
+ "../../../types/**/*.ts",
+ "../../../configs/app/**/*.ts",
+ "../../../global.d.ts",
+ "./index.ts",
+ "./schema.ts"
+ ],
+ "tsc-alias": {
+ "verbose": true,
+ "resolveFullPaths": true,
+ }
+}
+
\ No newline at end of file
diff --git a/explorer/frontend/deploy/tools/envs-validator/webpack.config.js b/explorer/frontend/deploy/tools/envs-validator/webpack.config.js
new file mode 100644
index 000000000..b62c19d07
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/webpack.config.js
@@ -0,0 +1,25 @@
+const path = require('path');
+const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
+
+module.exports = {
+ mode: 'production',
+ target: 'node',
+ entry: path.resolve(__dirname) + '/index.ts',
+ module: {
+ rules: [
+ {
+ test: /\.tsx?$/,
+ use: 'ts-loader',
+ exclude: /node_modules/,
+ },
+ ],
+ },
+ resolve: {
+ extensions: [ '.tsx', '.ts', '.js' ],
+ plugins: [ new TsconfigPathsPlugin({ configFile: './tsconfig.json' }) ],
+ },
+ output: {
+ filename: 'index.js',
+ path: path.resolve(__dirname),
+ },
+};
diff --git a/explorer/frontend/deploy/tools/envs-validator/yarn.lock b/explorer/frontend/deploy/tools/envs-validator/yarn.lock
new file mode 100644
index 000000000..2e8a42d34
--- /dev/null
+++ b/explorer/frontend/deploy/tools/envs-validator/yarn.lock
@@ -0,0 +1,989 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@discoveryjs/json-ext@^0.5.0":
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
+ integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
+
+"@jridgewell/gen-mapping@^0.3.0":
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098"
+ integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==
+ dependencies:
+ "@jridgewell/set-array" "^1.0.1"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+ "@jridgewell/trace-mapping" "^0.3.9"
+
+"@jridgewell/resolve-uri@3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
+ integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
+
+"@jridgewell/resolve-uri@^3.1.0":
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
+ integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
+
+"@jridgewell/set-array@^1.0.1":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
+ integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
+
+"@jridgewell/source-map@^0.3.3":
+ version "0.3.5"
+ resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91"
+ integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.0"
+ "@jridgewell/trace-mapping" "^0.3.9"
+
+"@jridgewell/sourcemap-codec@1.4.14":
+ version "1.4.14"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
+ integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
+
+"@jridgewell/sourcemap-codec@^1.4.10":
+ version "1.4.15"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
+ integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
+
+"@jridgewell/sourcemap-codec@^1.4.14":
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a"
+ integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
+
+"@jridgewell/trace-mapping@^0.3.20":
+ version "0.3.25"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0"
+ integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==
+ dependencies:
+ "@jridgewell/resolve-uri" "^3.1.0"
+ "@jridgewell/sourcemap-codec" "^1.4.14"
+
+"@jridgewell/trace-mapping@^0.3.9":
+ version "0.3.18"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6"
+ integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==
+ dependencies:
+ "@jridgewell/resolve-uri" "3.1.0"
+ "@jridgewell/sourcemap-codec" "1.4.14"
+
+"@types/estree@^1.0.5":
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
+ integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
+
+"@types/json-schema@^7.0.8":
+ version "7.0.12"
+ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb"
+ integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==
+
+"@types/node@*":
+ version "20.4.2"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.2.tgz#129cc9ae69f93824f92fac653eebfb4812ab4af9"
+ integrity sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==
+
+"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1":
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb"
+ integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==
+ dependencies:
+ "@webassemblyjs/helper-numbers" "1.11.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+
+"@webassemblyjs/floating-point-hex-parser@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431"
+ integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==
+
+"@webassemblyjs/helper-api-error@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768"
+ integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==
+
+"@webassemblyjs/helper-buffer@1.12.1":
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6"
+ integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==
+
+"@webassemblyjs/helper-numbers@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5"
+ integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==
+ dependencies:
+ "@webassemblyjs/floating-point-hex-parser" "1.11.6"
+ "@webassemblyjs/helper-api-error" "1.11.6"
+ "@xtuc/long" "4.2.2"
+
+"@webassemblyjs/helper-wasm-bytecode@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9"
+ integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==
+
+"@webassemblyjs/helper-wasm-section@1.12.1":
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf"
+ integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@webassemblyjs/helper-buffer" "1.12.1"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/wasm-gen" "1.12.1"
+
+"@webassemblyjs/ieee754@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a"
+ integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==
+ dependencies:
+ "@xtuc/ieee754" "^1.2.0"
+
+"@webassemblyjs/leb128@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7"
+ integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==
+ dependencies:
+ "@xtuc/long" "4.2.2"
+
+"@webassemblyjs/utf8@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a"
+ integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==
+
+"@webassemblyjs/wasm-edit@^1.12.1":
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b"
+ integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@webassemblyjs/helper-buffer" "1.12.1"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/helper-wasm-section" "1.12.1"
+ "@webassemblyjs/wasm-gen" "1.12.1"
+ "@webassemblyjs/wasm-opt" "1.12.1"
+ "@webassemblyjs/wasm-parser" "1.12.1"
+ "@webassemblyjs/wast-printer" "1.12.1"
+
+"@webassemblyjs/wasm-gen@1.12.1":
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547"
+ integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/ieee754" "1.11.6"
+ "@webassemblyjs/leb128" "1.11.6"
+ "@webassemblyjs/utf8" "1.11.6"
+
+"@webassemblyjs/wasm-opt@1.12.1":
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5"
+ integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@webassemblyjs/helper-buffer" "1.12.1"
+ "@webassemblyjs/wasm-gen" "1.12.1"
+ "@webassemblyjs/wasm-parser" "1.12.1"
+
+"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1":
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937"
+ integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@webassemblyjs/helper-api-error" "1.11.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/ieee754" "1.11.6"
+ "@webassemblyjs/leb128" "1.11.6"
+ "@webassemblyjs/utf8" "1.11.6"
+
+"@webassemblyjs/wast-printer@1.12.1":
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac"
+ integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@xtuc/long" "4.2.2"
+
+"@webpack-cli/configtest@^2.1.1":
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646"
+ integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==
+
+"@webpack-cli/info@^2.0.2":
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd"
+ integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==
+
+"@webpack-cli/serve@^2.0.5":
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e"
+ integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==
+
+"@xtuc/ieee754@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
+ integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==
+
+"@xtuc/long@4.2.2":
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
+ integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
+
+acorn-import-attributes@^1.9.5:
+ version "1.9.5"
+ resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef"
+ integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==
+
+acorn@^8.7.1, acorn@^8.8.2:
+ version "8.10.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5"
+ integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
+
+ajv-keywords@^3.5.2:
+ version "3.5.2"
+ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
+ integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
+
+ajv@^6.12.5:
+ version "6.12.6"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
+ integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ fast-json-stable-stringify "^2.0.0"
+ json-schema-traverse "^0.4.1"
+ uri-js "^4.2.2"
+
+ansi-styles@^4.1.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
+ integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
+ dependencies:
+ color-convert "^2.0.1"
+
+braces@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
+ integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
+ dependencies:
+ fill-range "^7.1.1"
+
+browserslist@^4.21.10:
+ version "4.24.2"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.2.tgz#f5845bc91069dbd55ee89faf9822e1d885d16580"
+ integrity sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==
+ dependencies:
+ caniuse-lite "^1.0.30001669"
+ electron-to-chromium "^1.5.41"
+ node-releases "^2.0.18"
+ update-browserslist-db "^1.1.1"
+
+buffer-from@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
+ integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
+
+caniuse-lite@^1.0.30001669:
+ version "1.0.30001673"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001673.tgz#5aa291557af1c71340e809987367410aab7a5a9e"
+ integrity sha512-WTrjUCSMp3LYX0nE12ECkV0a+e6LC85E0Auz75555/qr78Oc8YWhEPNfDd6SHdtlCMSzqtuXY0uyEMNRcsKpKw==
+
+chalk@^4.1.0:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+ integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
+chrome-trace-event@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac"
+ integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==
+
+clone-deep@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
+ integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==
+ dependencies:
+ is-plain-object "^2.0.4"
+ kind-of "^6.0.2"
+ shallow-clone "^3.0.0"
+
+color-convert@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
+ integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+ dependencies:
+ color-name "~1.1.4"
+
+color-name@~1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+colorette@^2.0.14:
+ version "2.0.20"
+ resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
+ integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==
+
+commander@^10.0.1:
+ version "10.0.1"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
+ integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
+
+commander@^2.20.0:
+ version "2.20.3"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
+ integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+
+cross-spawn@^7.0.3:
+ version "7.0.6"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
+ integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
+dotenv-cli@^7.2.1:
+ version "7.2.1"
+ resolved "https://registry.yarnpkg.com/dotenv-cli/-/dotenv-cli-7.2.1.tgz#e595afd9ebfb721df9da809a435b9aa966c92062"
+ integrity sha512-ODHbGTskqRtXAzZapDPvgNuDVQApu4oKX8lZW7Y0+9hKA6le1ZJlyRS687oU9FXjOVEDU/VFV6zI125HzhM1UQ==
+ dependencies:
+ cross-spawn "^7.0.3"
+ dotenv "^16.0.0"
+ dotenv-expand "^10.0.0"
+ minimist "^1.2.6"
+
+dotenv-expand@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37"
+ integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==
+
+dotenv@^16.0.0:
+ version "16.3.1"
+ resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e"
+ integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==
+
+electron-to-chromium@^1.5.41:
+ version "1.5.47"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.47.tgz#ef0751bc19b28be8ee44cd8405309de3bf3b20c7"
+ integrity sha512-zS5Yer0MOYw4rtK2iq43cJagHZ8sXN0jDHDKzB+86gSBSAI4v07S97mcq+Gs2vclAxSh1j7vOAHxSVgduiiuVQ==
+
+enhanced-resolve@^5.0.0, enhanced-resolve@^5.7.0:
+ version "5.15.0"
+ resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35"
+ integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==
+ dependencies:
+ graceful-fs "^4.2.4"
+ tapable "^2.2.0"
+
+enhanced-resolve@^5.17.1:
+ version "5.17.1"
+ resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15"
+ integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==
+ dependencies:
+ graceful-fs "^4.2.4"
+ tapable "^2.2.0"
+
+envinfo@^7.7.3:
+ version "7.10.0"
+ resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.10.0.tgz#55146e3909cc5fe63c22da63fb15b05aeac35b13"
+ integrity sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==
+
+es-module-lexer@^1.2.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.3.0.tgz#6be9c9e0b4543a60cd166ff6f8b4e9dae0b0c16f"
+ integrity sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==
+
+escalade@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
+ integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
+
+eslint-scope@5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
+ integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^4.1.1"
+
+esrecurse@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
+ integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
+ dependencies:
+ estraverse "^5.2.0"
+
+estraverse@^4.1.1:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
+ integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+
+estraverse@^5.2.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
+ integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
+
+events@^3.2.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
+ integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
+
+fast-deep-equal@^3.1.1:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
+ integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
+fast-json-stable-stringify@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
+ integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
+
+fastest-levenshtein@^1.0.12:
+ version "1.0.16"
+ resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5"
+ integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==
+
+fill-range@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
+ integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+find-up@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
+ integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
+ dependencies:
+ locate-path "^5.0.0"
+ path-exists "^4.0.0"
+
+function-bind@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+ integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+
+glob-to-regexp@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
+ integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
+
+graceful-fs@^4.1.2, graceful-fs@^4.2.11, graceful-fs@^4.2.4:
+ version "4.2.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
+ integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
+
+has-flag@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+ integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
+has@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+ integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+ dependencies:
+ function-bind "^1.1.1"
+
+import-local@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4"
+ integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==
+ dependencies:
+ pkg-dir "^4.2.0"
+ resolve-cwd "^3.0.0"
+
+interpret@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4"
+ integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==
+
+is-core-module@^2.11.0:
+ version "2.12.1"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd"
+ integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==
+ dependencies:
+ has "^1.0.3"
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+is-plain-object@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
+ integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==
+ dependencies:
+ isobject "^3.0.1"
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+ integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
+
+isobject@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
+ integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==
+
+jest-worker@^27.4.5:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0"
+ integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==
+ dependencies:
+ "@types/node" "*"
+ merge-stream "^2.0.0"
+ supports-color "^8.0.0"
+
+json-parse-even-better-errors@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
+ integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
+
+json-schema-traverse@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+ integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+
+json5@^2.2.2:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
+ integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
+
+kind-of@^6.0.2:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
+ integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
+
+loader-runner@^4.2.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1"
+ integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==
+
+locate-path@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
+ integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
+ dependencies:
+ p-locate "^4.1.0"
+
+lru-cache@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
+ integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
+ dependencies:
+ yallist "^4.0.0"
+
+merge-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
+ integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
+
+micromatch@^4.0.0:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
+ integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
+ dependencies:
+ braces "^3.0.3"
+ picomatch "^2.3.1"
+
+mime-db@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
+ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+mime-types@^2.1.27:
+ version "2.1.35"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
+ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+ dependencies:
+ mime-db "1.52.0"
+
+minimist@^1.2.6:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
+ integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+
+neo-async@^2.6.2:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
+ integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
+
+node-releases@^2.0.18:
+ version "2.0.18"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f"
+ integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==
+
+p-limit@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
+ integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
+ dependencies:
+ p-try "^2.0.0"
+
+p-locate@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
+ integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
+ dependencies:
+ p-limit "^2.2.0"
+
+p-try@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+ integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+
+path-exists@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
+path-key@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
+ integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+
+path-parse@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+
+picocolors@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
+ integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
+
+picomatch@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+pkg-dir@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
+ integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
+ dependencies:
+ find-up "^4.0.0"
+
+property-expr@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.5.tgz#278bdb15308ae16af3e3b9640024524f4dc02cb4"
+ integrity sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==
+
+punycode@^2.1.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
+ integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==
+
+randombytes@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
+ integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
+ dependencies:
+ safe-buffer "^5.1.0"
+
+rechoir@^0.8.0:
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22"
+ integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==
+ dependencies:
+ resolve "^1.20.0"
+
+resolve-cwd@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
+ integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==
+ dependencies:
+ resolve-from "^5.0.0"
+
+resolve-from@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
+ integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
+
+resolve@^1.20.0:
+ version "1.22.2"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f"
+ integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==
+ dependencies:
+ is-core-module "^2.11.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+safe-buffer@^5.1.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
+schema-utils@^3.1.1, schema-utils@^3.2.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe"
+ integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==
+ dependencies:
+ "@types/json-schema" "^7.0.8"
+ ajv "^6.12.5"
+ ajv-keywords "^3.5.2"
+
+semver@^7.3.4:
+ version "7.5.4"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
+ integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
+ dependencies:
+ lru-cache "^6.0.0"
+
+serialize-javascript@^6.0.1:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2"
+ integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==
+ dependencies:
+ randombytes "^2.1.0"
+
+shallow-clone@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
+ integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==
+ dependencies:
+ kind-of "^6.0.2"
+
+shebang-command@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
+ integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
+ dependencies:
+ shebang-regex "^3.0.0"
+
+shebang-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
+ integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+
+source-map-support@~0.5.20:
+ version "0.5.21"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
+ integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
+ dependencies:
+ buffer-from "^1.0.0"
+ source-map "^0.6.0"
+
+source-map@^0.6.0:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+strip-bom@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
+ integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==
+
+supports-color@^7.1.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
+ integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-color@^8.0.0:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
+ integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-preserve-symlinks-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
+ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
+tapable@^2.1.1, tapable@^2.2.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
+ integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
+
+terser-webpack-plugin@^5.3.10:
+ version "5.3.10"
+ resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199"
+ integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==
+ dependencies:
+ "@jridgewell/trace-mapping" "^0.3.20"
+ jest-worker "^27.4.5"
+ schema-utils "^3.1.1"
+ serialize-javascript "^6.0.1"
+ terser "^5.26.0"
+
+terser@^5.26.0:
+ version "5.36.0"
+ resolved "https://registry.yarnpkg.com/terser/-/terser-5.36.0.tgz#8b0dbed459ac40ff7b4c9fd5a3a2029de105180e"
+ integrity sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==
+ dependencies:
+ "@jridgewell/source-map" "^0.3.3"
+ acorn "^8.8.2"
+ commander "^2.20.0"
+ source-map-support "~0.5.20"
+
+tiny-case@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/tiny-case/-/tiny-case-1.0.3.tgz#d980d66bc72b5d5a9ca86fb7c9ffdb9c898ddd03"
+ integrity sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+toposort@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330"
+ integrity sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==
+
+ts-loader@^9.4.4:
+ version "9.4.4"
+ resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.4.4.tgz#6ceaf4d58dcc6979f84125335904920884b7cee4"
+ integrity sha512-MLukxDHBl8OJ5Dk3y69IsKVFRA/6MwzEqBgh+OXMPB/OD01KQuWPFd1WAQP8a5PeSCAxfnkhiuWqfmFJzJQt9w==
+ dependencies:
+ chalk "^4.1.0"
+ enhanced-resolve "^5.0.0"
+ micromatch "^4.0.0"
+ semver "^7.3.4"
+
+tsconfig-paths-webpack-plugin@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.1.0.tgz#3c6892c5e7319c146eee1e7302ed9e6f2be4f763"
+ integrity sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==
+ dependencies:
+ chalk "^4.1.0"
+ enhanced-resolve "^5.7.0"
+ tsconfig-paths "^4.1.2"
+
+tsconfig-paths@^4.1.2:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c"
+ integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==
+ dependencies:
+ json5 "^2.2.2"
+ minimist "^1.2.6"
+ strip-bom "^3.0.0"
+
+type-fest@^2.19.0:
+ version "2.19.0"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b"
+ integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==
+
+update-browserslist-db@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5"
+ integrity sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==
+ dependencies:
+ escalade "^3.2.0"
+ picocolors "^1.1.0"
+
+uri-js@^4.2.2:
+ version "4.4.1"
+ resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
+ integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
+ dependencies:
+ punycode "^2.1.0"
+
+watchpack@^2.4.1:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da"
+ integrity sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==
+ dependencies:
+ glob-to-regexp "^0.4.1"
+ graceful-fs "^4.1.2"
+
+webpack-cli@^5.1.4:
+ version "5.1.4"
+ resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b"
+ integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==
+ dependencies:
+ "@discoveryjs/json-ext" "^0.5.0"
+ "@webpack-cli/configtest" "^2.1.1"
+ "@webpack-cli/info" "^2.0.2"
+ "@webpack-cli/serve" "^2.0.5"
+ colorette "^2.0.14"
+ commander "^10.0.1"
+ cross-spawn "^7.0.3"
+ envinfo "^7.7.3"
+ fastest-levenshtein "^1.0.12"
+ import-local "^3.0.2"
+ interpret "^3.1.1"
+ rechoir "^0.8.0"
+ webpack-merge "^5.7.3"
+
+webpack-merge@^5.7.3:
+ version "5.9.0"
+ resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.9.0.tgz#dc160a1c4cf512ceca515cc231669e9ddb133826"
+ integrity sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==
+ dependencies:
+ clone-deep "^4.0.1"
+ wildcard "^2.0.0"
+
+webpack-sources@^3.2.3:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
+ integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
+
+webpack@^5.88.2:
+ version "5.95.0"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.95.0.tgz#8fd8c454fa60dad186fbe36c400a55848307b4c0"
+ integrity sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==
+ dependencies:
+ "@types/estree" "^1.0.5"
+ "@webassemblyjs/ast" "^1.12.1"
+ "@webassemblyjs/wasm-edit" "^1.12.1"
+ "@webassemblyjs/wasm-parser" "^1.12.1"
+ acorn "^8.7.1"
+ acorn-import-attributes "^1.9.5"
+ browserslist "^4.21.10"
+ chrome-trace-event "^1.0.2"
+ enhanced-resolve "^5.17.1"
+ es-module-lexer "^1.2.1"
+ eslint-scope "5.1.1"
+ events "^3.2.0"
+ glob-to-regexp "^0.4.1"
+ graceful-fs "^4.2.11"
+ json-parse-even-better-errors "^2.3.1"
+ loader-runner "^4.2.0"
+ mime-types "^2.1.27"
+ neo-async "^2.6.2"
+ schema-utils "^3.2.0"
+ tapable "^2.1.1"
+ terser-webpack-plugin "^5.3.10"
+ watchpack "^2.4.1"
+ webpack-sources "^3.2.3"
+
+which@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
+ integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+ dependencies:
+ isexe "^2.0.0"
+
+wildcard@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67"
+ integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==
+
+yallist@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
+ integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+
+yup@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/yup/-/yup-1.2.0.tgz#9e51af0c63bdfc9be0fdc6c10aa0710899d8aff6"
+ integrity sha512-PPqYKSAXjpRCgLgLKVGPA33v5c/WgEx3wi6NFjIiegz90zSwyMpvTFp/uGcVnnbx6to28pgnzp/q8ih3QRjLMQ==
+ dependencies:
+ property-expr "^2.0.5"
+ tiny-case "^1.0.3"
+ toposort "^2.0.2"
+ type-fest "^2.19.0"
diff --git a/explorer/frontend/deploy/tools/favicon-generator/.gitignore b/explorer/frontend/deploy/tools/favicon-generator/.gitignore
new file mode 100644
index 000000000..8b8c2bf2a
--- /dev/null
+++ b/explorer/frontend/deploy/tools/favicon-generator/.gitignore
@@ -0,0 +1,4 @@
+/node_modules
+/public
+.env
+/output
\ No newline at end of file
diff --git a/explorer/frontend/deploy/tools/favicon-generator/index.js b/explorer/frontend/deploy/tools/favicon-generator/index.js
new file mode 100644
index 000000000..b552a9f6c
--- /dev/null
+++ b/explorer/frontend/deploy/tools/favicon-generator/index.js
@@ -0,0 +1,71 @@
+/* eslint-disable no-console */
+const { favicons } = require('favicons');
+const fs = require('fs/promises');
+const path = require('path');
+
+generateFavicons();
+
+async function generateFavicons() {
+ console.log('Generating favicons...');
+ const masterUrl = process.env.MASTER_URL;
+ try {
+ if (!masterUrl) {
+ throw new Error('FAVICON_MASTER_URL or NEXT_PUBLIC_NETWORK_ICON must be set');
+ }
+
+ const fetch = await import('node-fetch');
+ const response = await fetch.default(masterUrl);
+ const buffer = await response.arrayBuffer();
+ const source = Buffer.from(buffer);
+
+ const configuration = {
+ path: '/output',
+ appName: 'Blockscout',
+ icons: {
+ android: true,
+ appleIcon: {
+ background: 'transparent',
+ },
+ appleStartup: false,
+ favicons: true,
+ windows: false,
+ yandex: false,
+ },
+ };
+
+ try {
+ const result = await favicons(source, configuration);
+
+ const outputDir = path.resolve(process.cwd(), 'output');
+ await fs.mkdir(outputDir, { recursive: true });
+
+ for (const image of result.images) {
+ // keep only necessary files
+ if (image.name === 'apple-touch-icon-180x180.png' || image.name === 'android-chrome-192x192.png' ||
+ (!image.name.startsWith('apple-touch-icon') && !image.name.startsWith('android-chrome'))
+ ) {
+ await fs.writeFile(path.join(outputDir, image.name), image.contents);
+ }
+
+ // copy android-chrome-192x192.png to logo-icon.png for marketing purposes
+ if (image.name === 'android-chrome-192x192.png') {
+ await fs.writeFile(path.join(outputDir, 'logo-icon.png'), image.contents);
+ }
+ }
+
+ for (const file of result.files) {
+ if (file.name !== 'manifest.webmanifest') {
+ await fs.writeFile(path.join(outputDir, file.name), file.contents);
+ }
+ }
+
+ console.log('Favicons generated successfully!');
+ } catch (faviconError) {
+ console.error('Error generating favicons:', faviconError);
+ process.exit(1);
+ }
+ } catch (error) {
+ console.error('Error in favicon generation process:', error);
+ process.exit(1);
+ }
+}
diff --git a/explorer/frontend/deploy/tools/favicon-generator/package.json b/explorer/frontend/deploy/tools/favicon-generator/package.json
new file mode 100644
index 000000000..f4127ccc3
--- /dev/null
+++ b/explorer/frontend/deploy/tools/favicon-generator/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "favicon-generator",
+ "version": "1.0.0",
+ "main": "index.js",
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "description": "",
+ "dependencies": {
+ "favicons": "^7.2.0",
+ "ts-loader": "^9.4.4",
+ "webpack": "^5.88.2",
+ "webpack-cli": "^5.1.4"
+ },
+ "devDependencies": {
+ "dotenv-cli": "^7.4.2",
+ "node-loader": "^2.0.0",
+ "tsconfig-paths-webpack-plugin": "^4.1.0"
+ }
+}
diff --git a/explorer/frontend/deploy/tools/favicon-generator/yarn.lock b/explorer/frontend/deploy/tools/favicon-generator/yarn.lock
new file mode 100644
index 000000000..11198f8e1
--- /dev/null
+++ b/explorer/frontend/deploy/tools/favicon-generator/yarn.lock
@@ -0,0 +1,1178 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@discoveryjs/json-ext@^0.5.0":
+ version "0.5.7"
+ resolved "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz"
+ integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
+
+"@emnapi/runtime@^1.2.0":
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.3.1.tgz#0fcaa575afc31f455fd33534c19381cfce6c6f60"
+ integrity sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==
+ dependencies:
+ tslib "^2.4.0"
+
+"@img/sharp-darwin-arm64@0.33.5":
+ version "0.33.5"
+ resolved "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz"
+ integrity sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==
+ optionalDependencies:
+ "@img/sharp-libvips-darwin-arm64" "1.0.4"
+
+"@img/sharp-darwin-x64@0.33.5":
+ version "0.33.5"
+ resolved "https://registry.yarnpkg.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz#e03d3451cd9e664faa72948cc70a403ea4063d61"
+ integrity sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==
+ optionalDependencies:
+ "@img/sharp-libvips-darwin-x64" "1.0.4"
+
+"@img/sharp-libvips-darwin-arm64@1.0.4":
+ version "1.0.4"
+ resolved "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz"
+ integrity sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==
+
+"@img/sharp-libvips-darwin-x64@1.0.4":
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz#e0456f8f7c623f9dbfbdc77383caa72281d86062"
+ integrity sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==
+
+"@img/sharp-libvips-linux-arm64@1.0.4":
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz#979b1c66c9a91f7ff2893556ef267f90ebe51704"
+ integrity sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==
+
+"@img/sharp-libvips-linux-arm@1.0.5":
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz#99f922d4e15216ec205dcb6891b721bfd2884197"
+ integrity sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==
+
+"@img/sharp-libvips-linux-s390x@1.0.4":
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz#f8a5eb1f374a082f72b3f45e2fb25b8118a8a5ce"
+ integrity sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==
+
+"@img/sharp-libvips-linux-x64@1.0.4":
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz#d4c4619cdd157774906e15770ee119931c7ef5e0"
+ integrity sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==
+
+"@img/sharp-libvips-linuxmusl-arm64@1.0.4":
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz#166778da0f48dd2bded1fa3033cee6b588f0d5d5"
+ integrity sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==
+
+"@img/sharp-libvips-linuxmusl-x64@1.0.4":
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz#93794e4d7720b077fcad3e02982f2f1c246751ff"
+ integrity sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==
+
+"@img/sharp-linux-arm64@0.33.5":
+ version "0.33.5"
+ resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz#edb0697e7a8279c9fc829a60fc35644c4839bb22"
+ integrity sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==
+ optionalDependencies:
+ "@img/sharp-libvips-linux-arm64" "1.0.4"
+
+"@img/sharp-linux-arm@0.33.5":
+ version "0.33.5"
+ resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz#422c1a352e7b5832842577dc51602bcd5b6f5eff"
+ integrity sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==
+ optionalDependencies:
+ "@img/sharp-libvips-linux-arm" "1.0.5"
+
+"@img/sharp-linux-s390x@0.33.5":
+ version "0.33.5"
+ resolved "https://registry.yarnpkg.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz#f5c077926b48e97e4a04d004dfaf175972059667"
+ integrity sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==
+ optionalDependencies:
+ "@img/sharp-libvips-linux-s390x" "1.0.4"
+
+"@img/sharp-linux-x64@0.33.5":
+ version "0.33.5"
+ resolved "https://registry.yarnpkg.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz#d806e0afd71ae6775cc87f0da8f2d03a7c2209cb"
+ integrity sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==
+ optionalDependencies:
+ "@img/sharp-libvips-linux-x64" "1.0.4"
+
+"@img/sharp-linuxmusl-arm64@0.33.5":
+ version "0.33.5"
+ resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz#252975b915894fb315af5deea174651e208d3d6b"
+ integrity sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==
+ optionalDependencies:
+ "@img/sharp-libvips-linuxmusl-arm64" "1.0.4"
+
+"@img/sharp-linuxmusl-x64@0.33.5":
+ version "0.33.5"
+ resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz#3f4609ac5d8ef8ec7dadee80b560961a60fd4f48"
+ integrity sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==
+ optionalDependencies:
+ "@img/sharp-libvips-linuxmusl-x64" "1.0.4"
+
+"@img/sharp-wasm32@0.33.5":
+ version "0.33.5"
+ resolved "https://registry.yarnpkg.com/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz#6f44f3283069d935bb5ca5813153572f3e6f61a1"
+ integrity sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==
+ dependencies:
+ "@emnapi/runtime" "^1.2.0"
+
+"@img/sharp-win32-ia32@0.33.5":
+ version "0.33.5"
+ resolved "https://registry.yarnpkg.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz#1a0c839a40c5351e9885628c85f2e5dfd02b52a9"
+ integrity sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==
+
+"@img/sharp-win32-x64@0.33.5":
+ version "0.33.5"
+ resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz#56f00962ff0c4e0eb93d34a047d29fa995e3e342"
+ integrity sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==
+
+"@jridgewell/gen-mapping@^0.3.5":
+ version "0.3.5"
+ resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz"
+ integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==
+ dependencies:
+ "@jridgewell/set-array" "^1.2.1"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+ "@jridgewell/trace-mapping" "^0.3.24"
+
+"@jridgewell/resolve-uri@^3.1.0":
+ version "3.1.2"
+ resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz"
+ integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
+
+"@jridgewell/set-array@^1.2.1":
+ version "1.2.1"
+ resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz"
+ integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==
+
+"@jridgewell/source-map@^0.3.3":
+ version "0.3.6"
+ resolved "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz"
+ integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.5"
+ "@jridgewell/trace-mapping" "^0.3.25"
+
+"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14":
+ version "1.5.0"
+ resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz"
+ integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
+
+"@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25":
+ version "0.3.25"
+ resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz"
+ integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==
+ dependencies:
+ "@jridgewell/resolve-uri" "^3.1.0"
+ "@jridgewell/sourcemap-codec" "^1.4.14"
+
+"@types/estree@^1.0.5":
+ version "1.0.6"
+ resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz"
+ integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
+
+"@types/json-schema@^7.0.8":
+ version "7.0.15"
+ resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz"
+ integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
+
+"@types/node@*":
+ version "22.7.9"
+ resolved "https://registry.npmjs.org/@types/node/-/node-22.7.9.tgz"
+ integrity sha512-jrTfRC7FM6nChvU7X2KqcrgquofrWLFDeYC1hKfwNWomVvrn7JIksqf344WN2X/y8xrgqBd2dJATZV4GbatBfg==
+ dependencies:
+ undici-types "~6.19.2"
+
+"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1":
+ version "1.12.1"
+ resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz"
+ integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==
+ dependencies:
+ "@webassemblyjs/helper-numbers" "1.11.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+
+"@webassemblyjs/floating-point-hex-parser@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz"
+ integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==
+
+"@webassemblyjs/helper-api-error@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz"
+ integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==
+
+"@webassemblyjs/helper-buffer@1.12.1":
+ version "1.12.1"
+ resolved "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz"
+ integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==
+
+"@webassemblyjs/helper-numbers@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz"
+ integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==
+ dependencies:
+ "@webassemblyjs/floating-point-hex-parser" "1.11.6"
+ "@webassemblyjs/helper-api-error" "1.11.6"
+ "@xtuc/long" "4.2.2"
+
+"@webassemblyjs/helper-wasm-bytecode@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz"
+ integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==
+
+"@webassemblyjs/helper-wasm-section@1.12.1":
+ version "1.12.1"
+ resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz"
+ integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@webassemblyjs/helper-buffer" "1.12.1"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/wasm-gen" "1.12.1"
+
+"@webassemblyjs/ieee754@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz"
+ integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==
+ dependencies:
+ "@xtuc/ieee754" "^1.2.0"
+
+"@webassemblyjs/leb128@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz"
+ integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==
+ dependencies:
+ "@xtuc/long" "4.2.2"
+
+"@webassemblyjs/utf8@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz"
+ integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==
+
+"@webassemblyjs/wasm-edit@^1.12.1":
+ version "1.12.1"
+ resolved "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz"
+ integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@webassemblyjs/helper-buffer" "1.12.1"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/helper-wasm-section" "1.12.1"
+ "@webassemblyjs/wasm-gen" "1.12.1"
+ "@webassemblyjs/wasm-opt" "1.12.1"
+ "@webassemblyjs/wasm-parser" "1.12.1"
+ "@webassemblyjs/wast-printer" "1.12.1"
+
+"@webassemblyjs/wasm-gen@1.12.1":
+ version "1.12.1"
+ resolved "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz"
+ integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/ieee754" "1.11.6"
+ "@webassemblyjs/leb128" "1.11.6"
+ "@webassemblyjs/utf8" "1.11.6"
+
+"@webassemblyjs/wasm-opt@1.12.1":
+ version "1.12.1"
+ resolved "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz"
+ integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@webassemblyjs/helper-buffer" "1.12.1"
+ "@webassemblyjs/wasm-gen" "1.12.1"
+ "@webassemblyjs/wasm-parser" "1.12.1"
+
+"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1":
+ version "1.12.1"
+ resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz"
+ integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@webassemblyjs/helper-api-error" "1.11.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/ieee754" "1.11.6"
+ "@webassemblyjs/leb128" "1.11.6"
+ "@webassemblyjs/utf8" "1.11.6"
+
+"@webassemblyjs/wast-printer@1.12.1":
+ version "1.12.1"
+ resolved "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz"
+ integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@xtuc/long" "4.2.2"
+
+"@webpack-cli/configtest@^2.1.1":
+ version "2.1.1"
+ resolved "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz"
+ integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==
+
+"@webpack-cli/info@^2.0.2":
+ version "2.0.2"
+ resolved "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz"
+ integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==
+
+"@webpack-cli/serve@^2.0.5":
+ version "2.0.5"
+ resolved "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz"
+ integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==
+
+"@xtuc/ieee754@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz"
+ integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==
+
+"@xtuc/long@4.2.2":
+ version "4.2.2"
+ resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz"
+ integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
+
+acorn-import-attributes@^1.9.5:
+ version "1.9.5"
+ resolved "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz"
+ integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==
+
+acorn@^8.7.1, acorn@^8.8.2:
+ version "8.13.0"
+ resolved "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz"
+ integrity sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==
+
+ajv-keywords@^3.5.2:
+ version "3.5.2"
+ resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz"
+ integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
+
+ajv@^6.12.5:
+ version "6.12.6"
+ resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz"
+ integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ fast-json-stable-stringify "^2.0.0"
+ json-schema-traverse "^0.4.1"
+ uri-js "^4.2.2"
+
+ansi-styles@^4.1.0:
+ version "4.3.0"
+ resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz"
+ integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
+ dependencies:
+ color-convert "^2.0.1"
+
+big.js@^5.2.2:
+ version "5.2.2"
+ resolved "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz"
+ integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
+
+braces@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz"
+ integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
+ dependencies:
+ fill-range "^7.1.1"
+
+browserslist@^4.21.10:
+ version "4.24.2"
+ resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz"
+ integrity sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==
+ dependencies:
+ caniuse-lite "^1.0.30001669"
+ electron-to-chromium "^1.5.41"
+ node-releases "^2.0.18"
+ update-browserslist-db "^1.1.1"
+
+buffer-from@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz"
+ integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
+
+caniuse-lite@^1.0.30001669:
+ version "1.0.30001669"
+ resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz"
+ integrity sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==
+
+chalk@^4.1.0:
+ version "4.1.2"
+ resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
+ integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
+chrome-trace-event@^1.0.2:
+ version "1.0.4"
+ resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz"
+ integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==
+
+clone-deep@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz"
+ integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==
+ dependencies:
+ is-plain-object "^2.0.4"
+ kind-of "^6.0.2"
+ shallow-clone "^3.0.0"
+
+color-convert@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz"
+ integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+ dependencies:
+ color-name "~1.1.4"
+
+color-name@^1.0.0, color-name@~1.1.4:
+ version "1.1.4"
+ resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
+ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+color-string@^1.9.0:
+ version "1.9.1"
+ resolved "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz"
+ integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==
+ dependencies:
+ color-name "^1.0.0"
+ simple-swizzle "^0.2.2"
+
+color@^4.2.3:
+ version "4.2.3"
+ resolved "https://registry.npmjs.org/color/-/color-4.2.3.tgz"
+ integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==
+ dependencies:
+ color-convert "^2.0.1"
+ color-string "^1.9.0"
+
+colorette@^2.0.14:
+ version "2.0.20"
+ resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz"
+ integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==
+
+commander@^10.0.1:
+ version "10.0.1"
+ resolved "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz"
+ integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
+
+commander@^2.20.0:
+ version "2.20.3"
+ resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz"
+ integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+
+cross-spawn@^7.0.3:
+ version "7.0.6"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
+ integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
+detect-libc@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz"
+ integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==
+
+dotenv-cli@^7.4.2:
+ version "7.4.2"
+ resolved "https://registry.npmjs.org/dotenv-cli/-/dotenv-cli-7.4.2.tgz"
+ integrity sha512-SbUj8l61zIbzyhIbg0FwPJq6+wjbzdn9oEtozQpZ6kW2ihCcapKVZj49oCT3oPM+mgQm+itgvUQcG5szxVrZTA==
+ dependencies:
+ cross-spawn "^7.0.3"
+ dotenv "^16.3.0"
+ dotenv-expand "^10.0.0"
+ minimist "^1.2.6"
+
+dotenv-expand@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz"
+ integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==
+
+dotenv@^16.3.0:
+ version "16.4.5"
+ resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz"
+ integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==
+
+electron-to-chromium@^1.5.41:
+ version "1.5.43"
+ resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.43.tgz"
+ integrity sha512-NxnmFBHDl5Sachd2P46O7UJiMaMHMLSofoIWVJq3mj8NJgG0umiSeljAVP9lGzjI0UDLJJ5jjoGjcrB8RSbjLQ==
+
+emojis-list@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz"
+ integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
+
+enhanced-resolve@^5.0.0, enhanced-resolve@^5.17.1, enhanced-resolve@^5.7.0:
+ version "5.17.1"
+ resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz"
+ integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==
+ dependencies:
+ graceful-fs "^4.2.4"
+ tapable "^2.2.0"
+
+envinfo@^7.7.3:
+ version "7.14.0"
+ resolved "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz"
+ integrity sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==
+
+es-module-lexer@^1.2.1:
+ version "1.5.4"
+ resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz"
+ integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==
+
+escalade@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz"
+ integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
+
+escape-html@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz"
+ integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
+
+eslint-scope@5.1.1:
+ version "5.1.1"
+ resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz"
+ integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^4.1.1"
+
+esrecurse@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz"
+ integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
+ dependencies:
+ estraverse "^5.2.0"
+
+estraverse@^4.1.1:
+ version "4.3.0"
+ resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz"
+ integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+
+estraverse@^5.2.0:
+ version "5.3.0"
+ resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz"
+ integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
+
+events@^3.2.0:
+ version "3.3.0"
+ resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz"
+ integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
+
+fast-deep-equal@^3.1.1:
+ version "3.1.3"
+ resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz"
+ integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
+fast-json-stable-stringify@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz"
+ integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
+
+fastest-levenshtein@^1.0.12:
+ version "1.0.16"
+ resolved "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz"
+ integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==
+
+favicons@^7.2.0:
+ version "7.2.0"
+ resolved "https://registry.npmjs.org/favicons/-/favicons-7.2.0.tgz"
+ integrity sha512-k/2rVBRIRzOeom3wI9jBPaSEvoTSQEW4iM0EveBmBBKFxO8mSyyRWtDlfC3VnEfu0avmjrMzy8/ZFPSe6F71Hw==
+ dependencies:
+ escape-html "^1.0.3"
+ sharp "^0.33.1"
+ xml2js "^0.6.1"
+
+fill-range@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz"
+ integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+find-up@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz"
+ integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
+ dependencies:
+ locate-path "^5.0.0"
+ path-exists "^4.0.0"
+
+flat@^5.0.2:
+ version "5.0.2"
+ resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz"
+ integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
+
+function-bind@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"
+ integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
+
+glob-to-regexp@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz"
+ integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
+
+graceful-fs@^4.1.2, graceful-fs@^4.2.11, graceful-fs@^4.2.4:
+ version "4.2.11"
+ resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz"
+ integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
+
+has-flag@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz"
+ integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
+hasown@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz"
+ integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
+ dependencies:
+ function-bind "^1.1.2"
+
+import-local@^3.0.2:
+ version "3.2.0"
+ resolved "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz"
+ integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==
+ dependencies:
+ pkg-dir "^4.2.0"
+ resolve-cwd "^3.0.0"
+
+interpret@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz"
+ integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==
+
+is-arrayish@^0.3.1:
+ version "0.3.2"
+ resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz"
+ integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
+
+is-core-module@^2.13.0:
+ version "2.15.1"
+ resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz"
+ integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==
+ dependencies:
+ hasown "^2.0.2"
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+is-plain-object@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz"
+ integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==
+ dependencies:
+ isobject "^3.0.1"
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz"
+ integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
+
+isobject@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz"
+ integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==
+
+jest-worker@^27.4.5:
+ version "27.5.1"
+ resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz"
+ integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==
+ dependencies:
+ "@types/node" "*"
+ merge-stream "^2.0.0"
+ supports-color "^8.0.0"
+
+json-parse-even-better-errors@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz"
+ integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
+
+json-schema-traverse@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz"
+ integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+
+json5@^2.1.2, json5@^2.2.2:
+ version "2.2.3"
+ resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz"
+ integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
+
+kind-of@^6.0.2:
+ version "6.0.3"
+ resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz"
+ integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
+
+loader-runner@^4.2.0:
+ version "4.3.0"
+ resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz"
+ integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==
+
+loader-utils@^2.0.0:
+ version "2.0.4"
+ resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz"
+ integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==
+ dependencies:
+ big.js "^5.2.2"
+ emojis-list "^3.0.0"
+ json5 "^2.1.2"
+
+locate-path@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz"
+ integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
+ dependencies:
+ p-locate "^4.1.0"
+
+merge-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz"
+ integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
+
+micromatch@^4.0.0:
+ version "4.0.8"
+ resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz"
+ integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
+ dependencies:
+ braces "^3.0.3"
+ picomatch "^2.3.1"
+
+mime-db@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz"
+ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+mime-types@^2.1.27:
+ version "2.1.35"
+ resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz"
+ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+ dependencies:
+ mime-db "1.52.0"
+
+minimist@^1.2.6:
+ version "1.2.8"
+ resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz"
+ integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+
+neo-async@^2.6.2:
+ version "2.6.2"
+ resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz"
+ integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
+
+node-loader@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/node-loader/-/node-loader-2.0.0.tgz#9109a6d828703fd3e0aa03c1baec12a798071562"
+ integrity sha512-I5VN34NO4/5UYJaUBtkrODPWxbobrE4hgDqPrjB25yPkonFhCmZ146vTH+Zg417E9Iwoh1l/MbRs1apc5J295Q==
+ dependencies:
+ loader-utils "^2.0.0"
+
+node-releases@^2.0.18:
+ version "2.0.18"
+ resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz"
+ integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==
+
+p-limit@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz"
+ integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
+ dependencies:
+ p-try "^2.0.0"
+
+p-locate@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz"
+ integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
+ dependencies:
+ p-limit "^2.2.0"
+
+p-try@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz"
+ integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+
+path-exists@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz"
+ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
+path-key@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz"
+ integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+
+path-parse@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+
+picocolors@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz"
+ integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
+
+picomatch@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+pkg-dir@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz"
+ integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
+ dependencies:
+ find-up "^4.0.0"
+
+punycode@^2.1.0:
+ version "2.3.1"
+ resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz"
+ integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
+
+randombytes@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz"
+ integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
+ dependencies:
+ safe-buffer "^5.1.0"
+
+rechoir@^0.8.0:
+ version "0.8.0"
+ resolved "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz"
+ integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==
+ dependencies:
+ resolve "^1.20.0"
+
+resolve-cwd@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz"
+ integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==
+ dependencies:
+ resolve-from "^5.0.0"
+
+resolve-from@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz"
+ integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
+
+resolve@^1.20.0:
+ version "1.22.8"
+ resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz"
+ integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
+ dependencies:
+ is-core-module "^2.13.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+safe-buffer@^5.1.0:
+ version "5.2.1"
+ resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz"
+ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
+sax@>=0.6.0:
+ version "1.4.1"
+ resolved "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz"
+ integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==
+
+schema-utils@^3.1.1, schema-utils@^3.2.0:
+ version "3.3.0"
+ resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz"
+ integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==
+ dependencies:
+ "@types/json-schema" "^7.0.8"
+ ajv "^6.12.5"
+ ajv-keywords "^3.5.2"
+
+semver@^7.3.4, semver@^7.6.3:
+ version "7.6.3"
+ resolved "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz"
+ integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
+
+serialize-javascript@^6.0.1:
+ version "6.0.2"
+ resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz"
+ integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==
+ dependencies:
+ randombytes "^2.1.0"
+
+shallow-clone@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz"
+ integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==
+ dependencies:
+ kind-of "^6.0.2"
+
+sharp@^0.33.1:
+ version "0.33.5"
+ resolved "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz"
+ integrity sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==
+ dependencies:
+ color "^4.2.3"
+ detect-libc "^2.0.3"
+ semver "^7.6.3"
+ optionalDependencies:
+ "@img/sharp-darwin-arm64" "0.33.5"
+ "@img/sharp-darwin-x64" "0.33.5"
+ "@img/sharp-libvips-darwin-arm64" "1.0.4"
+ "@img/sharp-libvips-darwin-x64" "1.0.4"
+ "@img/sharp-libvips-linux-arm" "1.0.5"
+ "@img/sharp-libvips-linux-arm64" "1.0.4"
+ "@img/sharp-libvips-linux-s390x" "1.0.4"
+ "@img/sharp-libvips-linux-x64" "1.0.4"
+ "@img/sharp-libvips-linuxmusl-arm64" "1.0.4"
+ "@img/sharp-libvips-linuxmusl-x64" "1.0.4"
+ "@img/sharp-linux-arm" "0.33.5"
+ "@img/sharp-linux-arm64" "0.33.5"
+ "@img/sharp-linux-s390x" "0.33.5"
+ "@img/sharp-linux-x64" "0.33.5"
+ "@img/sharp-linuxmusl-arm64" "0.33.5"
+ "@img/sharp-linuxmusl-x64" "0.33.5"
+ "@img/sharp-wasm32" "0.33.5"
+ "@img/sharp-win32-ia32" "0.33.5"
+ "@img/sharp-win32-x64" "0.33.5"
+
+shebang-command@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz"
+ integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
+ dependencies:
+ shebang-regex "^3.0.0"
+
+shebang-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz"
+ integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+
+simple-swizzle@^0.2.2:
+ version "0.2.2"
+ resolved "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz"
+ integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==
+ dependencies:
+ is-arrayish "^0.3.1"
+
+source-map-support@~0.5.20:
+ version "0.5.21"
+ resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz"
+ integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
+ dependencies:
+ buffer-from "^1.0.0"
+ source-map "^0.6.0"
+
+source-map@^0.6.0:
+ version "0.6.1"
+ resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz"
+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+source-map@^0.7.4:
+ version "0.7.4"
+ resolved "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz"
+ integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==
+
+strip-bom@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz"
+ integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==
+
+supports-color@^7.1.0:
+ version "7.2.0"
+ resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"
+ integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-color@^8.0.0:
+ version "8.1.1"
+ resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz"
+ integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-preserve-symlinks-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz"
+ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
+tapable@^2.1.1, tapable@^2.2.0:
+ version "2.2.1"
+ resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz"
+ integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
+
+terser-webpack-plugin@^5.3.10:
+ version "5.3.10"
+ resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz"
+ integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==
+ dependencies:
+ "@jridgewell/trace-mapping" "^0.3.20"
+ jest-worker "^27.4.5"
+ schema-utils "^3.1.1"
+ serialize-javascript "^6.0.1"
+ terser "^5.26.0"
+
+terser@^5.26.0:
+ version "5.36.0"
+ resolved "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz"
+ integrity sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==
+ dependencies:
+ "@jridgewell/source-map" "^0.3.3"
+ acorn "^8.8.2"
+ commander "^2.20.0"
+ source-map-support "~0.5.20"
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+ts-loader@^9.4.4:
+ version "9.5.1"
+ resolved "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz"
+ integrity sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==
+ dependencies:
+ chalk "^4.1.0"
+ enhanced-resolve "^5.0.0"
+ micromatch "^4.0.0"
+ semver "^7.3.4"
+ source-map "^0.7.4"
+
+tsconfig-paths-webpack-plugin@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.1.0.tgz"
+ integrity sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==
+ dependencies:
+ chalk "^4.1.0"
+ enhanced-resolve "^5.7.0"
+ tsconfig-paths "^4.1.2"
+
+tsconfig-paths@^4.1.2:
+ version "4.2.0"
+ resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz"
+ integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==
+ dependencies:
+ json5 "^2.2.2"
+ minimist "^1.2.6"
+ strip-bom "^3.0.0"
+
+tslib@^2.4.0:
+ version "2.8.0"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.0.tgz#d124c86c3c05a40a91e6fdea4021bd31d377971b"
+ integrity sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==
+
+undici-types@~6.19.2:
+ version "6.19.8"
+ resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz"
+ integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==
+
+update-browserslist-db@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz"
+ integrity sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==
+ dependencies:
+ escalade "^3.2.0"
+ picocolors "^1.1.0"
+
+uri-js@^4.2.2:
+ version "4.4.1"
+ resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz"
+ integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
+ dependencies:
+ punycode "^2.1.0"
+
+watchpack@^2.4.1:
+ version "2.4.2"
+ resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz"
+ integrity sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==
+ dependencies:
+ glob-to-regexp "^0.4.1"
+ graceful-fs "^4.1.2"
+
+webpack-cli@^5.1.4:
+ version "5.1.4"
+ resolved "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz"
+ integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==
+ dependencies:
+ "@discoveryjs/json-ext" "^0.5.0"
+ "@webpack-cli/configtest" "^2.1.1"
+ "@webpack-cli/info" "^2.0.2"
+ "@webpack-cli/serve" "^2.0.5"
+ colorette "^2.0.14"
+ commander "^10.0.1"
+ cross-spawn "^7.0.3"
+ envinfo "^7.7.3"
+ fastest-levenshtein "^1.0.12"
+ import-local "^3.0.2"
+ interpret "^3.1.1"
+ rechoir "^0.8.0"
+ webpack-merge "^5.7.3"
+
+webpack-merge@^5.7.3:
+ version "5.10.0"
+ resolved "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz"
+ integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==
+ dependencies:
+ clone-deep "^4.0.1"
+ flat "^5.0.2"
+ wildcard "^2.0.0"
+
+webpack-sources@^3.2.3:
+ version "3.2.3"
+ resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz"
+ integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
+
+webpack@^5.88.2:
+ version "5.95.0"
+ resolved "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz"
+ integrity sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==
+ dependencies:
+ "@types/estree" "^1.0.5"
+ "@webassemblyjs/ast" "^1.12.1"
+ "@webassemblyjs/wasm-edit" "^1.12.1"
+ "@webassemblyjs/wasm-parser" "^1.12.1"
+ acorn "^8.7.1"
+ acorn-import-attributes "^1.9.5"
+ browserslist "^4.21.10"
+ chrome-trace-event "^1.0.2"
+ enhanced-resolve "^5.17.1"
+ es-module-lexer "^1.2.1"
+ eslint-scope "5.1.1"
+ events "^3.2.0"
+ glob-to-regexp "^0.4.1"
+ graceful-fs "^4.2.11"
+ json-parse-even-better-errors "^2.3.1"
+ loader-runner "^4.2.0"
+ mime-types "^2.1.27"
+ neo-async "^2.6.2"
+ schema-utils "^3.2.0"
+ tapable "^2.1.1"
+ terser-webpack-plugin "^5.3.10"
+ watchpack "^2.4.1"
+ webpack-sources "^3.2.3"
+
+which@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz"
+ integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+ dependencies:
+ isexe "^2.0.0"
+
+wildcard@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz"
+ integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==
+
+xml2js@^0.6.1:
+ version "0.6.2"
+ resolved "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz"
+ integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==
+ dependencies:
+ sax ">=0.6.0"
+ xmlbuilder "~11.0.0"
+
+xmlbuilder@~11.0.0:
+ version "11.0.1"
+ resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz"
+ integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
diff --git a/explorer/frontend/deploy/tools/feature-reporter/.gitignore b/explorer/frontend/deploy/tools/feature-reporter/.gitignore
new file mode 100644
index 000000000..cefc90f67
--- /dev/null
+++ b/explorer/frontend/deploy/tools/feature-reporter/.gitignore
@@ -0,0 +1,3 @@
+/node_modules
+/build
+index.js
\ No newline at end of file
diff --git a/explorer/frontend/deploy/tools/feature-reporter/dev.sh b/explorer/frontend/deploy/tools/feature-reporter/dev.sh
new file mode 100755
index 000000000..183698a81
--- /dev/null
+++ b/explorer/frontend/deploy/tools/feature-reporter/dev.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+rm -rf ./build
+yarn compile_config
+yarn build
+dotenv -e ../../../configs/envs/.env.main -e ../../../configs/envs/.env.secrets yarn print_report
\ No newline at end of file
diff --git a/explorer/frontend/deploy/tools/feature-reporter/entry.js b/explorer/frontend/deploy/tools/feature-reporter/entry.js
new file mode 100644
index 000000000..01a298903
--- /dev/null
+++ b/explorer/frontend/deploy/tools/feature-reporter/entry.js
@@ -0,0 +1,23 @@
+/* eslint-disable no-console */
+const config = require('./build/configs/app').default;
+
+run();
+
+async function run() {
+ console.log();
+ try {
+ console.log(`📋 Here is the list of the features enabled for the running instance.
+To adjust their configuration, please refer to the documentation - https://github.com/blockscout/frontend/blob/main/docs/ENVS.md#app-features
+ `);
+ Object.entries(config.features)
+ .forEach(([ , feature ]) => {
+ const mark = feature.isEnabled ? 'v' : ' ';
+ console.log(` [${ mark }] ${ feature.title }`);
+ });
+
+ } catch (error) {
+ console.log('🚨 An error occurred while generating the feature report.');
+ process.exit(1);
+ }
+ console.log();
+}
diff --git a/explorer/frontend/deploy/tools/feature-reporter/package.json b/explorer/frontend/deploy/tools/feature-reporter/package.json
new file mode 100644
index 000000000..136886831
--- /dev/null
+++ b/explorer/frontend/deploy/tools/feature-reporter/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "feature-reporter",
+ "version": "1.0.0",
+ "main": "index.js",
+ "license": "MIT",
+ "scripts": {
+ "compile_config": "yarn tsc -p ./tsconfig.json && yarn tsc-alias -p ./tsconfig.json",
+ "build": "yarn webpack-cli -c ./webpack.config.js",
+ "print_report": "node ./index.js",
+ "dev": "./dev.sh"
+ },
+ "dependencies": {
+ "tsc": "^2.0.4",
+ "tsc-alias": "^1.8.7",
+ "typescript": "5.1",
+ "webpack": "^5.88.2",
+ "webpack-cli": "^5.1.4"
+ },
+ "devDependencies": {
+ "dotenv-cli": "^7.2.1"
+ }
+}
diff --git a/explorer/frontend/deploy/tools/feature-reporter/tsconfig.json b/explorer/frontend/deploy/tools/feature-reporter/tsconfig.json
new file mode 100644
index 000000000..86b706822
--- /dev/null
+++ b/explorer/frontend/deploy/tools/feature-reporter/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "extends": "../../../tsconfig.json",
+ "compilerOptions": {
+ "noEmit": false,
+ "module": "CommonJS",
+ "moduleResolution": "node",
+ "outDir": "./build",
+ "paths": {
+ "nextjs-routes": ["./nextjs/nextjs-routes.d.ts"],
+ }
+ },
+ "include": [ "../../../configs/app/index.ts", "../../../global.d.ts" ],
+ "tsc-alias": {
+ "verbose": true,
+ "resolveFullPaths": true,
+ }
+}
diff --git a/explorer/frontend/deploy/tools/feature-reporter/webpack.config.js b/explorer/frontend/deploy/tools/feature-reporter/webpack.config.js
new file mode 100644
index 000000000..41363dfee
--- /dev/null
+++ b/explorer/frontend/deploy/tools/feature-reporter/webpack.config.js
@@ -0,0 +1,13 @@
+const path = require('path');
+module.exports = {
+ mode: 'production',
+ target: 'node',
+ entry: path.resolve(__dirname, '/entry.js'),
+ resolve: {
+ extensions: [ '.js' ],
+ },
+ output: {
+ filename: 'index.js',
+ path: path.resolve(__dirname),
+ },
+};
diff --git a/explorer/frontend/deploy/tools/feature-reporter/yarn.lock b/explorer/frontend/deploy/tools/feature-reporter/yarn.lock
new file mode 100644
index 000000000..7eeb603bb
--- /dev/null
+++ b/explorer/frontend/deploy/tools/feature-reporter/yarn.lock
@@ -0,0 +1,1060 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@discoveryjs/json-ext@^0.5.0":
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
+ integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
+
+"@jridgewell/gen-mapping@^0.3.0":
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098"
+ integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==
+ dependencies:
+ "@jridgewell/set-array" "^1.0.1"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+ "@jridgewell/trace-mapping" "^0.3.9"
+
+"@jridgewell/resolve-uri@^3.1.0":
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721"
+ integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==
+
+"@jridgewell/set-array@^1.0.1":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
+ integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
+
+"@jridgewell/source-map@^0.3.3":
+ version "0.3.5"
+ resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91"
+ integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.0"
+ "@jridgewell/trace-mapping" "^0.3.9"
+
+"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14":
+ version "1.4.15"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
+ integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
+
+"@jridgewell/trace-mapping@^0.3.20":
+ version "0.3.25"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0"
+ integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==
+ dependencies:
+ "@jridgewell/resolve-uri" "^3.1.0"
+ "@jridgewell/sourcemap-codec" "^1.4.14"
+
+"@jridgewell/trace-mapping@^0.3.9":
+ version "0.3.19"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz#f8a3249862f91be48d3127c3cfe992f79b4b8811"
+ integrity sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==
+ dependencies:
+ "@jridgewell/resolve-uri" "^3.1.0"
+ "@jridgewell/sourcemap-codec" "^1.4.14"
+
+"@nodelib/fs.scandir@2.1.5":
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
+ integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
+ dependencies:
+ "@nodelib/fs.stat" "2.0.5"
+ run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
+ integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
+
+"@nodelib/fs.walk@^1.2.3":
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
+ integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
+ dependencies:
+ "@nodelib/fs.scandir" "2.1.5"
+ fastq "^1.6.0"
+
+"@types/estree@^1.0.5":
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
+ integrity "sha1-Yo7/7q4gZKG055946B2Ht+X8e1A= sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="
+
+"@types/json-schema@^7.0.8":
+ version "7.0.12"
+ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb"
+ integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==
+
+"@types/node@*":
+ version "20.4.8"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.8.tgz#b5dda19adaa473a9bf0ab5cbd8f30ec7d43f5c85"
+ integrity sha512-0mHckf6D2DiIAzh8fM8f3HQCvMKDpK94YQ0DSVkfWTG9BZleYIWudw9cJxX8oCk9bM+vAkDyujDV6dmKHbvQpg==
+
+"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1":
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb"
+ integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==
+ dependencies:
+ "@webassemblyjs/helper-numbers" "1.11.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+
+"@webassemblyjs/floating-point-hex-parser@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431"
+ integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==
+
+"@webassemblyjs/helper-api-error@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768"
+ integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==
+
+"@webassemblyjs/helper-buffer@1.12.1":
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6"
+ integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==
+
+"@webassemblyjs/helper-numbers@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5"
+ integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==
+ dependencies:
+ "@webassemblyjs/floating-point-hex-parser" "1.11.6"
+ "@webassemblyjs/helper-api-error" "1.11.6"
+ "@xtuc/long" "4.2.2"
+
+"@webassemblyjs/helper-wasm-bytecode@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9"
+ integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==
+
+"@webassemblyjs/helper-wasm-section@1.12.1":
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf"
+ integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@webassemblyjs/helper-buffer" "1.12.1"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/wasm-gen" "1.12.1"
+
+"@webassemblyjs/ieee754@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a"
+ integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==
+ dependencies:
+ "@xtuc/ieee754" "^1.2.0"
+
+"@webassemblyjs/leb128@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7"
+ integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==
+ dependencies:
+ "@xtuc/long" "4.2.2"
+
+"@webassemblyjs/utf8@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a"
+ integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==
+
+"@webassemblyjs/wasm-edit@^1.12.1":
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b"
+ integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@webassemblyjs/helper-buffer" "1.12.1"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/helper-wasm-section" "1.12.1"
+ "@webassemblyjs/wasm-gen" "1.12.1"
+ "@webassemblyjs/wasm-opt" "1.12.1"
+ "@webassemblyjs/wasm-parser" "1.12.1"
+ "@webassemblyjs/wast-printer" "1.12.1"
+
+"@webassemblyjs/wasm-gen@1.12.1":
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547"
+ integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/ieee754" "1.11.6"
+ "@webassemblyjs/leb128" "1.11.6"
+ "@webassemblyjs/utf8" "1.11.6"
+
+"@webassemblyjs/wasm-opt@1.12.1":
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5"
+ integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@webassemblyjs/helper-buffer" "1.12.1"
+ "@webassemblyjs/wasm-gen" "1.12.1"
+ "@webassemblyjs/wasm-parser" "1.12.1"
+
+"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1":
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937"
+ integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@webassemblyjs/helper-api-error" "1.11.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/ieee754" "1.11.6"
+ "@webassemblyjs/leb128" "1.11.6"
+ "@webassemblyjs/utf8" "1.11.6"
+
+"@webassemblyjs/wast-printer@1.12.1":
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac"
+ integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==
+ dependencies:
+ "@webassemblyjs/ast" "1.12.1"
+ "@xtuc/long" "4.2.2"
+
+"@webpack-cli/configtest@^2.1.1":
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646"
+ integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==
+
+"@webpack-cli/info@^2.0.2":
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd"
+ integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==
+
+"@webpack-cli/serve@^2.0.5":
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e"
+ integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==
+
+"@xtuc/ieee754@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
+ integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==
+
+"@xtuc/long@4.2.2":
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
+ integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
+
+acorn-import-attributes@^1.9.5:
+ version "1.9.5"
+ resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef"
+ integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==
+
+acorn@^8.7.1, acorn@^8.8.2:
+ version "8.10.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5"
+ integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
+
+ajv-keywords@^3.5.2:
+ version "3.5.2"
+ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
+ integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
+
+ajv@^6.12.5:
+ version "6.12.6"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
+ integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ fast-json-stable-stringify "^2.0.0"
+ json-schema-traverse "^0.4.1"
+ uri-js "^4.2.2"
+
+anymatch@~3.1.2:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
+ integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
+ dependencies:
+ normalize-path "^3.0.0"
+ picomatch "^2.0.4"
+
+array-union@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
+ integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+
+binary-extensions@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
+ integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
+
+braces@^3.0.3, braces@~3.0.2:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
+ integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
+ dependencies:
+ fill-range "^7.1.1"
+
+browserslist@^4.21.10:
+ version "4.24.2"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.2.tgz#f5845bc91069dbd55ee89faf9822e1d885d16580"
+ integrity "sha1-9YRbyRBp29Ve6J+vmCLh2IXRZYA= sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg=="
+ dependencies:
+ caniuse-lite "^1.0.30001669"
+ electron-to-chromium "^1.5.41"
+ node-releases "^2.0.18"
+ update-browserslist-db "^1.1.1"
+
+buffer-from@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
+ integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
+
+caniuse-lite@^1.0.30001669:
+ version "1.0.30001673"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001673.tgz#5aa291557af1c71340e809987367410aab7a5a9e"
+ integrity "sha1-WqKRVXrxxxNA6AmYc2dBCqt6Wp4= sha512-WTrjUCSMp3LYX0nE12ECkV0a+e6LC85E0Auz75555/qr78Oc8YWhEPNfDd6SHdtlCMSzqtuXY0uyEMNRcsKpKw=="
+
+chokidar@^3.5.3:
+ version "3.5.3"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
+ integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
+ dependencies:
+ anymatch "~3.1.2"
+ braces "~3.0.2"
+ glob-parent "~5.1.2"
+ is-binary-path "~2.1.0"
+ is-glob "~4.0.1"
+ normalize-path "~3.0.0"
+ readdirp "~3.6.0"
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+chrome-trace-event@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac"
+ integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==
+
+clone-deep@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
+ integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==
+ dependencies:
+ is-plain-object "^2.0.4"
+ kind-of "^6.0.2"
+ shallow-clone "^3.0.0"
+
+colorette@^2.0.14:
+ version "2.0.20"
+ resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
+ integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==
+
+commander@^10.0.1:
+ version "10.0.1"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
+ integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
+
+commander@^2.20.0:
+ version "2.20.3"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
+ integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+
+commander@^9.0.0:
+ version "9.5.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30"
+ integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==
+
+cross-spawn@^7.0.3:
+ version "7.0.6"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
+ integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
+dir-glob@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
+ integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
+ dependencies:
+ path-type "^4.0.0"
+
+dotenv-cli@^7.2.1:
+ version "7.2.1"
+ resolved "https://registry.yarnpkg.com/dotenv-cli/-/dotenv-cli-7.2.1.tgz#e595afd9ebfb721df9da809a435b9aa966c92062"
+ integrity sha512-ODHbGTskqRtXAzZapDPvgNuDVQApu4oKX8lZW7Y0+9hKA6le1ZJlyRS687oU9FXjOVEDU/VFV6zI125HzhM1UQ==
+ dependencies:
+ cross-spawn "^7.0.3"
+ dotenv "^16.0.0"
+ dotenv-expand "^10.0.0"
+ minimist "^1.2.6"
+
+dotenv-expand@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37"
+ integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==
+
+dotenv@^16.0.0:
+ version "16.3.1"
+ resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e"
+ integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==
+
+electron-to-chromium@^1.5.41:
+ version "1.5.47"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.47.tgz#ef0751bc19b28be8ee44cd8405309de3bf3b20c7"
+ integrity "sha1-7wdRvBmyi+juRM2EBTCd4787IMc= sha512-zS5Yer0MOYw4rtK2iq43cJagHZ8sXN0jDHDKzB+86gSBSAI4v07S97mcq+Gs2vclAxSh1j7vOAHxSVgduiiuVQ=="
+
+enhanced-resolve@^5.17.1:
+ version "5.17.1"
+ resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15"
+ integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==
+ dependencies:
+ graceful-fs "^4.2.4"
+ tapable "^2.2.0"
+
+envinfo@^7.7.3:
+ version "7.10.0"
+ resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.10.0.tgz#55146e3909cc5fe63c22da63fb15b05aeac35b13"
+ integrity sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==
+
+es-module-lexer@^1.2.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.3.0.tgz#6be9c9e0b4543a60cd166ff6f8b4e9dae0b0c16f"
+ integrity sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==
+
+escalade@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
+ integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
+
+eslint-scope@5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
+ integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^4.1.1"
+
+esrecurse@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
+ integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
+ dependencies:
+ estraverse "^5.2.0"
+
+estraverse@^4.1.1:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
+ integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+
+estraverse@^5.2.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
+ integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
+
+events@^3.2.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
+ integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
+
+fast-deep-equal@^3.1.1:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
+ integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
+fast-glob@^3.2.9:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4"
+ integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==
+ dependencies:
+ "@nodelib/fs.stat" "^2.0.2"
+ "@nodelib/fs.walk" "^1.2.3"
+ glob-parent "^5.1.2"
+ merge2 "^1.3.0"
+ micromatch "^4.0.4"
+
+fast-json-stable-stringify@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
+ integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
+
+fastest-levenshtein@^1.0.12:
+ version "1.0.16"
+ resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5"
+ integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==
+
+fastq@^1.6.0:
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
+ integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==
+ dependencies:
+ reusify "^1.0.4"
+
+fill-range@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
+ integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+find-up@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
+ integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
+ dependencies:
+ locate-path "^5.0.0"
+ path-exists "^4.0.0"
+
+fsevents@~2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
+ integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+
+function-bind@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+ integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+
+glob-parent@^5.1.2, glob-parent@~5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+ dependencies:
+ is-glob "^4.0.1"
+
+glob-to-regexp@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
+ integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
+
+globby@^11.0.4:
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
+ integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
+ dependencies:
+ array-union "^2.1.0"
+ dir-glob "^3.0.1"
+ fast-glob "^3.2.9"
+ ignore "^5.2.0"
+ merge2 "^1.4.1"
+ slash "^3.0.0"
+
+graceful-fs@^4.1.2, graceful-fs@^4.2.11, graceful-fs@^4.2.4:
+ version "4.2.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
+ integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
+
+has-flag@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+ integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
+has@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+ integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+ dependencies:
+ function-bind "^1.1.1"
+
+ignore@^5.2.0:
+ version "5.2.4"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
+ integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
+
+import-local@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4"
+ integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==
+ dependencies:
+ pkg-dir "^4.2.0"
+ resolve-cwd "^3.0.0"
+
+interpret@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4"
+ integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==
+
+is-binary-path@~2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
+ integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
+ dependencies:
+ binary-extensions "^2.0.0"
+
+is-core-module@^2.13.0:
+ version "2.13.0"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db"
+ integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==
+ dependencies:
+ has "^1.0.3"
+
+is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+ integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-glob@^4.0.1, is-glob@~4.0.1:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+is-plain-object@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
+ integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==
+ dependencies:
+ isobject "^3.0.1"
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+ integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
+
+isobject@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
+ integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==
+
+jest-worker@^27.4.5:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0"
+ integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==
+ dependencies:
+ "@types/node" "*"
+ merge-stream "^2.0.0"
+ supports-color "^8.0.0"
+
+json-parse-even-better-errors@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
+ integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
+
+json-schema-traverse@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+ integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+
+kind-of@^6.0.2:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
+ integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
+
+loader-runner@^4.2.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1"
+ integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==
+
+locate-path@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
+ integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
+ dependencies:
+ p-locate "^4.1.0"
+
+merge-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
+ integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
+
+merge2@^1.3.0, merge2@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
+ integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+
+micromatch@^4.0.4:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
+ integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
+ dependencies:
+ braces "^3.0.3"
+ picomatch "^2.3.1"
+
+mime-db@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
+ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+mime-types@^2.1.27:
+ version "2.1.35"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
+ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+ dependencies:
+ mime-db "1.52.0"
+
+minimist@^1.2.6:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
+ integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+
+mylas@^2.1.9:
+ version "2.1.13"
+ resolved "https://registry.yarnpkg.com/mylas/-/mylas-2.1.13.tgz#1e23b37d58fdcc76e15d8a5ed23f9ae9fc0cbdf4"
+ integrity sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==
+
+neo-async@^2.6.2:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
+ integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
+
+node-releases@^2.0.18:
+ version "2.0.18"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f"
+ integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==
+
+normalize-path@^3.0.0, normalize-path@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
+ integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+
+p-limit@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
+ integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
+ dependencies:
+ p-try "^2.0.0"
+
+p-locate@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
+ integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
+ dependencies:
+ p-limit "^2.2.0"
+
+p-try@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+ integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+
+path-exists@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
+path-key@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
+ integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+
+path-parse@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+
+path-type@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
+ integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+
+picocolors@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
+ integrity "sha1-PTIa8+q5ObCDyPkpodEs2oHCa2s= sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
+
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+pkg-dir@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
+ integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
+ dependencies:
+ find-up "^4.0.0"
+
+plimit-lit@^1.2.6:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/plimit-lit/-/plimit-lit-1.5.0.tgz#f66df8a7041de1e965c4f1c0697ab486968a92a5"
+ integrity sha512-Eb/MqCb1Iv/ok4m1FqIXqvUKPISufcjZ605hl3KM/n8GaX8zfhtgdLwZU3vKjuHGh2O9Rjog/bHTq8ofIShdng==
+ dependencies:
+ queue-lit "^1.5.0"
+
+punycode@^2.1.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
+ integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==
+
+queue-lit@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/queue-lit/-/queue-lit-1.5.0.tgz#8197fdafda1edd615c8a0fc14c48353626e5160a"
+ integrity sha512-IslToJ4eiCEE9xwMzq3viOO5nH8sUWUCwoElrhNMozzr9IIt2qqvB4I+uHu/zJTQVqc9R5DFwok4ijNK1pU3fA==
+
+queue-microtask@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
+ integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+
+randombytes@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
+ integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
+ dependencies:
+ safe-buffer "^5.1.0"
+
+readdirp@~3.6.0:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
+ integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
+ dependencies:
+ picomatch "^2.2.1"
+
+rechoir@^0.8.0:
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22"
+ integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==
+ dependencies:
+ resolve "^1.20.0"
+
+resolve-cwd@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
+ integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==
+ dependencies:
+ resolve-from "^5.0.0"
+
+resolve-from@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
+ integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
+
+resolve@^1.20.0:
+ version "1.22.4"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34"
+ integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==
+ dependencies:
+ is-core-module "^2.13.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+reusify@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
+ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
+run-parallel@^1.1.9:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
+ integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+ dependencies:
+ queue-microtask "^1.2.2"
+
+safe-buffer@^5.1.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
+schema-utils@^3.1.1, schema-utils@^3.2.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe"
+ integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==
+ dependencies:
+ "@types/json-schema" "^7.0.8"
+ ajv "^6.12.5"
+ ajv-keywords "^3.5.2"
+
+serialize-javascript@^6.0.1:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2"
+ integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==
+ dependencies:
+ randombytes "^2.1.0"
+
+shallow-clone@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
+ integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==
+ dependencies:
+ kind-of "^6.0.2"
+
+shebang-command@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
+ integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
+ dependencies:
+ shebang-regex "^3.0.0"
+
+shebang-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
+ integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+
+slash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
+ integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
+
+source-map-support@~0.5.20:
+ version "0.5.21"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
+ integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
+ dependencies:
+ buffer-from "^1.0.0"
+ source-map "^0.6.0"
+
+source-map@^0.6.0:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+supports-color@^8.0.0:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
+ integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-preserve-symlinks-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
+ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
+tapable@^2.1.1, tapable@^2.2.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
+ integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
+
+terser-webpack-plugin@^5.3.10:
+ version "5.3.10"
+ resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199"
+ integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==
+ dependencies:
+ "@jridgewell/trace-mapping" "^0.3.20"
+ jest-worker "^27.4.5"
+ schema-utils "^3.1.1"
+ serialize-javascript "^6.0.1"
+ terser "^5.26.0"
+
+terser@^5.26.0:
+ version "5.36.0"
+ resolved "https://registry.yarnpkg.com/terser/-/terser-5.36.0.tgz#8b0dbed459ac40ff7b4c9fd5a3a2029de105180e"
+ integrity "sha1-iw2+1FmsQP97TJ/Vo6ICneEFGA4= sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w=="
+ dependencies:
+ "@jridgewell/source-map" "^0.3.3"
+ acorn "^8.8.2"
+ commander "^2.20.0"
+ source-map-support "~0.5.20"
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+tsc-alias@^1.8.7:
+ version "1.8.7"
+ resolved "https://registry.yarnpkg.com/tsc-alias/-/tsc-alias-1.8.7.tgz#4f8721b031a31345fa9f1fa8d3cf209d925abb88"
+ integrity sha512-59Q/zUQa3miTf99mLbSqaW0hi1jt4WoG8Uhe5hSZJHQpSoFW9eEwvW7jlKMHXWvT+zrzy3SN9PE/YBhQ+WVydA==
+ dependencies:
+ chokidar "^3.5.3"
+ commander "^9.0.0"
+ globby "^11.0.4"
+ mylas "^2.1.9"
+ normalize-path "^3.0.0"
+ plimit-lit "^1.2.6"
+
+tsc@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/tsc/-/tsc-2.0.4.tgz#5f6499146abea5dca4420b451fa4f2f9345238f5"
+ integrity sha512-fzoSieZI5KKJVBYGvwbVZs/J5za84f2lSTLPYf6AGiIf43tZ3GNrI1QzTLcjtyDDP4aLxd46RTZq1nQxe7+k5Q==
+
+typescript@5.1:
+ version "5.1.6"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274"
+ integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==
+
+update-browserslist-db@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5"
+ integrity "sha1-gIRvuh156CVH+2YfjRQeCUV1X+U= sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A=="
+ dependencies:
+ escalade "^3.2.0"
+ picocolors "^1.1.0"
+
+uri-js@^4.2.2:
+ version "4.4.1"
+ resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
+ integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
+ dependencies:
+ punycode "^2.1.0"
+
+watchpack@^2.4.1:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da"
+ integrity "sha1-L+6u1nQS58MxhOWnnKc4+9OFZNo= sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw=="
+ dependencies:
+ glob-to-regexp "^0.4.1"
+ graceful-fs "^4.1.2"
+
+webpack-cli@^5.1.4:
+ version "5.1.4"
+ resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b"
+ integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==
+ dependencies:
+ "@discoveryjs/json-ext" "^0.5.0"
+ "@webpack-cli/configtest" "^2.1.1"
+ "@webpack-cli/info" "^2.0.2"
+ "@webpack-cli/serve" "^2.0.5"
+ colorette "^2.0.14"
+ commander "^10.0.1"
+ cross-spawn "^7.0.3"
+ envinfo "^7.7.3"
+ fastest-levenshtein "^1.0.12"
+ import-local "^3.0.2"
+ interpret "^3.1.1"
+ rechoir "^0.8.0"
+ webpack-merge "^5.7.3"
+
+webpack-merge@^5.7.3:
+ version "5.9.0"
+ resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.9.0.tgz#dc160a1c4cf512ceca515cc231669e9ddb133826"
+ integrity sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==
+ dependencies:
+ clone-deep "^4.0.1"
+ wildcard "^2.0.0"
+
+webpack-sources@^3.2.3:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
+ integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
+
+webpack@^5.88.2:
+ version "5.95.0"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.95.0.tgz#8fd8c454fa60dad186fbe36c400a55848307b4c0"
+ integrity "sha1-j9jEVPpg2tGG++NsQApVhIMHtMA= sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q=="
+ dependencies:
+ "@types/estree" "^1.0.5"
+ "@webassemblyjs/ast" "^1.12.1"
+ "@webassemblyjs/wasm-edit" "^1.12.1"
+ "@webassemblyjs/wasm-parser" "^1.12.1"
+ acorn "^8.7.1"
+ acorn-import-attributes "^1.9.5"
+ browserslist "^4.21.10"
+ chrome-trace-event "^1.0.2"
+ enhanced-resolve "^5.17.1"
+ es-module-lexer "^1.2.1"
+ eslint-scope "5.1.1"
+ events "^3.2.0"
+ glob-to-regexp "^0.4.1"
+ graceful-fs "^4.2.11"
+ json-parse-even-better-errors "^2.3.1"
+ loader-runner "^4.2.0"
+ mime-types "^2.1.27"
+ neo-async "^2.6.2"
+ schema-utils "^3.2.0"
+ tapable "^2.1.1"
+ terser-webpack-plugin "^5.3.10"
+ watchpack "^2.4.1"
+ webpack-sources "^3.2.3"
+
+which@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
+ integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+ dependencies:
+ isexe "^2.0.0"
+
+wildcard@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67"
+ integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==
diff --git a/explorer/frontend/deploy/tools/sitemap-generator/.gitignore b/explorer/frontend/deploy/tools/sitemap-generator/.gitignore
new file mode 100644
index 000000000..30bc16279
--- /dev/null
+++ b/explorer/frontend/deploy/tools/sitemap-generator/.gitignore
@@ -0,0 +1 @@
+/node_modules
\ No newline at end of file
diff --git a/explorer/frontend/deploy/tools/sitemap-generator/next-sitemap.config.js b/explorer/frontend/deploy/tools/sitemap-generator/next-sitemap.config.js
new file mode 100644
index 000000000..820046fc4
--- /dev/null
+++ b/explorer/frontend/deploy/tools/sitemap-generator/next-sitemap.config.js
@@ -0,0 +1,203 @@
+/* eslint-disable no-console */
+const path = require('path');
+
+const stripTrailingSlash = (str) => str[str.length - 1] === '/' ? str.slice(0, -1) : str;
+
+const fetchResource = async(url, formatter) => {
+ console.log('🌀 [next-sitemap] Fetching resource:', url);
+ try {
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), 15_000);
+
+ const res = await fetch(url, {
+ signal: controller.signal,
+ });
+
+ clearTimeout(timeoutId);
+
+ if (res.ok) {
+ const data = await res.json();
+ console.log('✅ [next-sitemap] Data fetched for resource:', url);
+ return formatter(data);
+ }
+ } catch (error) {
+ if (error.name === 'AbortError') {
+ console.log('🚨 [next-sitemap] Request timeout for resource:', url);
+ } else {
+ console.log('🚨 [next-sitemap] Error fetching resource:', url, error);
+ }
+ }
+};
+
+const siteUrl = [
+ process.env.NEXT_PUBLIC_APP_PROTOCOL || 'https',
+ '://',
+ process.env.NEXT_PUBLIC_APP_HOST,
+ process.env.NEXT_PUBLIC_APP_PORT && ':' + process.env.NEXT_PUBLIC_APP_PORT,
+].filter(Boolean).join('');
+
+const apiUrl = (() => {
+ const baseUrl = [
+ process.env.NEXT_PUBLIC_API_PROTOCOL || 'https',
+ '://',
+ process.env.NEXT_PUBLIC_API_HOST,
+ process.env.NEXT_PUBLIC_API_PORT && ':' + process.env.NEXT_PUBLIC_API_PORT,
+ ].filter(Boolean).join('');
+
+ const basePath = stripTrailingSlash(process.env.NEXT_PUBLIC_API_BASE_PATH || '');
+
+ return `${ baseUrl }${ basePath }/api/v2`;
+})();
+
+/** @type {import('next-sitemap').IConfig} */
+module.exports = {
+ siteUrl,
+ generateIndexSitemap: false,
+ generateRobotsTxt: true,
+ robotsTxtOptions: {
+ policies: [
+ {
+ userAgent: '*',
+ allow: '/',
+ disallow: ['/auth/*', '/login', '/chakra', '/sprite', '/account/*'],
+ },
+ ],
+ },
+ sourceDir: path.resolve(process.cwd(), '../../../.next'),
+ outDir: path.resolve(process.cwd(), '../../../public'),
+ exclude: [
+ '/account/*',
+ '/auth/*',
+ '/login',
+ '/sprite',
+ '/chakra',
+ ],
+ transform: async(config, path) => {
+ switch (path) {
+ case '/mud-worlds':
+ if (process.env.NEXT_PUBLIC_HAS_MUD_FRAMEWORK !== 'true') {
+ return null;
+ }
+ break;
+ case '/batches':
+ case '/deposits':
+ if (!process.env.NEXT_PUBLIC_ROLLUP_TYPE) {
+ return null;
+ }
+ break;
+ case '/withdrawals':
+ if (!process.env.NEXT_PUBLIC_ROLLUP_TYPE && process.env.NEXT_PUBLIC_HAS_BEACON_CHAIN !== 'true') {
+ return null;
+ }
+ break;
+ case '/dispute-games':
+ if (process.env.NEXT_PUBLIC_ROLLUP_TYPE !== 'optimistic') {
+ return null;
+ }
+ break;
+ case '/blobs':
+ if (process.env.NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED !== 'true') {
+ return null;
+ }
+ break;
+ case '/name-domains':
+ if (!process.env.NEXT_PUBLIC_NAME_SERVICE_API_HOST) {
+ return null;
+ }
+ break;
+ case '/ops':
+ if (process.env.NEXT_PUBLIC_HAS_USER_OPS !== 'true') {
+ return null;
+ }
+ break;
+ case '/output-roots':
+ if (process.env.NEXT_PUBLIC_ROLLUP_OUTPUT_ROOTS_ENABLED !== 'true') {
+ return null;
+ }
+ break;
+ case '/interop-messages':
+ if (process.env.NEXT_PUBLIC_INTEROP_ENABLED !== 'true') {
+ return null;
+ }
+ break;
+ case '/pools':
+ if (process.env.NEXT_PUBLIC_DEX_POOLS_ENABLED !== 'true') {
+ return null;
+ }
+ break;
+ case '/advanced-filter':
+ if (process.env.NEXT_PUBLIC_ADVANCED_FILTER_ENABLED === 'false') {
+ return null;
+ }
+ break;
+ case '/apps':
+ if (process.env.NEXT_PUBLIC_MARKETPLACE_ENABLED !== 'true') {
+ return null;
+ }
+ break;
+ case '/api-docs':
+ if (process.env.NEXT_PUBLIC_API_SPEC_URL === 'none') {
+ return null;
+ }
+ break;
+ case '/gas-tracker':
+ if (process.env.NEXT_PUBLIC_GAS_TRACKER_ENABLED === 'false') {
+ return null;
+ }
+ break;
+ case '/graphql':
+ if (process.env.NEXT_PUBLIC_GRAPHIQL_TRANSACTION === 'none') {
+ return null;
+ }
+ break;
+ case '/stats':
+ if (!process.env.NEXT_PUBLIC_STATS_API_HOST) {
+ return null;
+ }
+ break;
+ case '/validators':
+ if (!process.env.NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE) {
+ return null;
+ }
+ break;
+ }
+
+ return {
+ loc: path,
+ changefreq: undefined,
+ priority: undefined,
+ lastmod: config.autoLastmod ? new Date().toISOString() : undefined,
+ alternateRefs: config.alternateRefs ?? [],
+ };
+ },
+ additionalPaths: async(config) => {
+ const addresses = fetchResource(
+ `${ apiUrl }/addresses`,
+ (data) => data.items.map(({ hash }) => `/address/${ hash }`),
+ );
+ const txs = fetchResource(
+ `${ apiUrl }/transactions?filter=validated`,
+ (data) => data.items.map(({ hash }) => `/tx/${ hash }`),
+ );
+ const blocks = fetchResource(
+ `${ apiUrl }/blocks?type=block`,
+ (data) => data.items.map(({ height }) => `/block/${ height }`),
+ );
+ const tokens = fetchResource(
+ `${ apiUrl }/tokens`,
+ (data) => data.items.map(({ address }) => `/token/${ address }`),
+ );
+ const contracts = fetchResource(
+ `${ apiUrl }/smart-contracts`,
+ (data) => data.items.map(({ address }) => `/address/${ address.hash }?tab=contract`),
+ );
+
+ return Promise.all([
+ ...(await addresses || []),
+ ...(await txs || []),
+ ...(await blocks || []),
+ ...(await tokens || []),
+ ...(await contracts || []),
+ ].map(path => config.transform(config, path)));
+ },
+};
diff --git a/explorer/frontend/deploy/tools/sitemap-generator/package.json b/explorer/frontend/deploy/tools/sitemap-generator/package.json
new file mode 100644
index 000000000..903f7a326
--- /dev/null
+++ b/explorer/frontend/deploy/tools/sitemap-generator/package.json
@@ -0,0 +1,12 @@
+{
+ "name": "sitemap-generator",
+ "version": "1.0.0",
+ "main": "index.js",
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "description": "",
+ "dependencies": {
+ "next-sitemap": "4.2.3"
+ }
+}
diff --git a/explorer/frontend/deploy/tools/sitemap-generator/yarn.lock b/explorer/frontend/deploy/tools/sitemap-generator/yarn.lock
new file mode 100644
index 000000000..165c1f047
--- /dev/null
+++ b/explorer/frontend/deploy/tools/sitemap-generator/yarn.lock
@@ -0,0 +1,147 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@corex/deepmerge@^4.0.43":
+ version "4.0.43"
+ resolved "https://registry.yarnpkg.com/@corex/deepmerge/-/deepmerge-4.0.43.tgz#9bd42559ebb41cc5a7fb7cfeea5f231c20977dca"
+ integrity sha512-N8uEMrMPL0cu/bdboEWpQYb/0i2K5Qn8eCsxzOmxSggJbbQte7ljMRoXm917AbntqTGOzdTu+vP3KOOzoC70HQ==
+
+"@next/env@^13.4.3":
+ version "13.5.8"
+ resolved "https://registry.yarnpkg.com/@next/env/-/env-13.5.8.tgz#404d3b3e5881b6a0510500c6cc97e3589a2e6371"
+ integrity sha512-YmiG58BqyZ2FjrF2+5uZExL2BrLr8RTQzLXNDJ8pJr0O+rPlOeDPXp1p1/4OrR3avDidzZo3D8QO2cuDv1KCkw==
+
+"@nodelib/fs.scandir@2.1.5":
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
+ integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
+ dependencies:
+ "@nodelib/fs.stat" "2.0.5"
+ run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
+ integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
+
+"@nodelib/fs.walk@^1.2.3":
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
+ integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
+ dependencies:
+ "@nodelib/fs.scandir" "2.1.5"
+ fastq "^1.6.0"
+
+braces@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
+ integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
+ dependencies:
+ fill-range "^7.1.1"
+
+fast-glob@^3.2.12:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129"
+ integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==
+ dependencies:
+ "@nodelib/fs.stat" "^2.0.2"
+ "@nodelib/fs.walk" "^1.2.3"
+ glob-parent "^5.1.2"
+ merge2 "^1.3.0"
+ micromatch "^4.0.4"
+
+fastq@^1.6.0:
+ version "1.18.0"
+ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.18.0.tgz#d631d7e25faffea81887fe5ea8c9010e1b36fee0"
+ integrity sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==
+ dependencies:
+ reusify "^1.0.4"
+
+fill-range@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
+ integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+glob-parent@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+ dependencies:
+ is-glob "^4.0.1"
+
+is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+ integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-glob@^4.0.1:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+merge2@^1.3.0:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
+ integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+
+micromatch@^4.0.4:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
+ integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
+ dependencies:
+ braces "^3.0.3"
+ picomatch "^2.3.1"
+
+minimist@^1.2.8:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
+ integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+
+next-sitemap@4.2.3:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/next-sitemap/-/next-sitemap-4.2.3.tgz#5db3f650351a51e84b9fd6b58c5af2f9257b5058"
+ integrity sha512-vjdCxeDuWDzldhCnyFCQipw5bfpl4HmZA7uoo3GAaYGjGgfL4Cxb1CiztPuWGmS+auYs7/8OekRS8C2cjdAsjQ==
+ dependencies:
+ "@corex/deepmerge" "^4.0.43"
+ "@next/env" "^13.4.3"
+ fast-glob "^3.2.12"
+ minimist "^1.2.8"
+
+picomatch@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+queue-microtask@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
+ integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+
+reusify@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
+ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
+run-parallel@^1.1.9:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
+ integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+ dependencies:
+ queue-microtask "^1.2.2"
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
diff --git a/explorer/frontend/deploy/values/review-l2/values.yaml.gotmpl b/explorer/frontend/deploy/values/review-l2/values.yaml.gotmpl
new file mode 100644
index 000000000..3a9173849
--- /dev/null
+++ b/explorer/frontend/deploy/values/review-l2/values.yaml.gotmpl
@@ -0,0 +1,79 @@
+fullNameOverride: bs-stack
+nameOverride: bs-stack
+imagePullSecrets:
+ - name: regcred
+config:
+ network:
+ id: 420
+ name: "Base"
+ shortname: Base
+ currency:
+ name: Ether
+ symbol: ETH
+ decimals: 18
+ account:
+ enabled: true
+ testnet: true
+blockscout:
+ enabled: false
+stats:
+ enabled: false
+frontend:
+ enabled: true
+ replicaCount: 1
+ image:
+ tag: review-{{ requiredEnv "GITHUB_REF_NAME_SLUG" }}
+ pullPolicy: Always
+ ingress:
+ enabled: true
+ annotations:
+ kubernetes.io/ingress.class: internal-and-public
+ nginx.ingress.kubernetes.io/proxy-body-size: 500m
+ nginx.ingress.kubernetes.io/client-max-body-size: "500M"
+ nginx.ingress.kubernetes.io/proxy-buffering: "on"
+ nginx.ingress.kubernetes.io/proxy-connect-timeout: "15m"
+ nginx.ingress.kubernetes.io/proxy-send-timeout: "15m"
+ nginx.ingress.kubernetes.io/proxy-read-timeout: "15m"
+ nginx.ingress.kubernetes.io/proxy-buffer-size: "128k"
+ nginx.ingress.kubernetes.io/proxy-buffers-number: "8"
+ cert-manager.io/cluster-issuer: "zerossl-prod"
+ hostname: review-l2-{{ requiredEnv "GITHUB_REF_NAME_SLUG" }}.k8s-dev.blockscout.com
+
+ resources:
+ limits:
+ memory: 768Mi
+ cpu: "1"
+ requests:
+ memory: 384Mi
+ cpu: 250m
+ env:
+ NEXT_PUBLIC_APP_ENV: review
+ NEXT_PUBLIC_NETWORK_LOGO: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/base.svg
+ NEXT_PUBLIC_NETWORK_ICON: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/base.svg
+ NEXT_PUBLIC_FEATURED_NETWORKS: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/base-mainnet.json
+ NEXT_PUBLIC_API_HOST: base.blockscout.com
+ NEXT_PUBLIC_LOGOUT_URL: https://blockscoutcom.us.auth0.com/v2/logout
+ NEXT_PUBLIC_STATS_API_HOST: https://stats-l2-base-mainnet.k8s-prod-1.blockscout.com
+ 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_NETWORK_RPC_URL: https://mainnet.base.org
+ NEXT_PUBLIC_WEB3_WALLETS: "['coinbase']"
+ NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET: true
+ NEXT_PUBLIC_HOMEPAGE_CHARTS: "['daily_txs']"
+ NEXT_PUBLIC_VISUALIZE_API_HOST: https://visualizer.services.blockscout.com
+ NEXT_PUBLIC_CONTRACT_INFO_API_HOST: https://contracts-info.services.blockscout.com
+ NEXT_PUBLIC_ADMIN_SERVICE_API_HOST: https://admin-rs.services.blockscout.com
+ NEXT_PUBLIC_NAME_SERVICE_API_HOST: https://bens.services.blockscout.com
+ NEXT_PUBLIC_METADATA_SERVICE_API_HOST: https://metadata.services.blockscout.com
+ NEXT_PUBLIC_ROLLUP_TYPE: optimistic
+ NEXT_PUBLIC_ROLLUP_L1_BASE_URL: https://eth.blockscout.com
+ NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL: https://app.optimism.io/bridge/withdraw
+ NEXT_PUBLIC_GRAPHIQL_TRANSACTION: 0x4a0ed8ddf751a7cb5297f827699117b0f6d21a0b2907594d300dc9fed75c7e62
+ NEXT_PUBLIC_USE_NEXT_JS_PROXY: true
+ NEXT_PUBLIC_NAVIGATION_LAYOUT: horizontal
+ NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES: "['/blocks','/name-domains']"
+ envFromSecret:
+ NEXT_PUBLIC_AUTH0_CLIENT_ID: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_AUTH0_CLIENT_ID
+ NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID
+ NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID
+ NEXT_PUBLIC_OG_IMAGE_URL: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/base-mainnet.png
+ NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY: ref+vault://deployment-values/blockscout/eth-sepolia/testnet?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/RE_CAPTCHA_CLIENT_KEY
diff --git a/explorer/frontend/deploy/values/review/values.yaml.gotmpl b/explorer/frontend/deploy/values/review/values.yaml.gotmpl
new file mode 100644
index 000000000..ecc6d34ac
--- /dev/null
+++ b/explorer/frontend/deploy/values/review/values.yaml.gotmpl
@@ -0,0 +1,89 @@
+fullNameOverride: bs-stack
+nameOverride: bs-stack
+imagePullSecrets:
+ - name: regcred
+config:
+ network:
+ id: "11155111"
+ name: Blockscout
+ shortname: Blockscout
+ currency:
+ name: Ether
+ symbol: ETH
+ decimals: 18
+ account:
+ enabled: true
+ testnet: true
+blockscout:
+ enabled: false
+stats:
+ enabled: false
+frontend:
+ enabled: true
+ replicaCount: 1
+ image:
+ tag: review-{{ requiredEnv "GITHUB_REF_NAME_SLUG" }}
+ pullPolicy: Always
+ ingress:
+ enabled: true
+ annotations:
+ kubernetes.io/ingress.class: internal-and-public
+ nginx.ingress.kubernetes.io/proxy-body-size: 500m
+ nginx.ingress.kubernetes.io/client-max-body-size: "500M"
+ nginx.ingress.kubernetes.io/proxy-buffering: "on"
+ nginx.ingress.kubernetes.io/proxy-connect-timeout: "15m"
+ nginx.ingress.kubernetes.io/proxy-send-timeout: "15m"
+ nginx.ingress.kubernetes.io/proxy-read-timeout: "15m"
+ nginx.ingress.kubernetes.io/proxy-buffer-size: "128k"
+ nginx.ingress.kubernetes.io/proxy-buffers-number: "8"
+ cert-manager.io/cluster-issuer: "zerossl-prod"
+ hostname: review-{{ requiredEnv "GITHUB_REF_NAME_SLUG" }}.k8s-dev.blockscout.com
+
+ resources:
+ limits:
+ memory: 768Mi
+ cpu: "1"
+ requests:
+ memory: 384Mi
+ cpu: 250m
+ env:
+ NEXT_PUBLIC_APP_ENV: review
+ NEXT_PUBLIC_FEATURED_NETWORKS: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/eth-sepolia.json
+ NEXT_PUBLIC_NETWORK_LOGO: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/sepolia.svg
+ NEXT_PUBLIC_NETWORK_ICON: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/sepolia.png
+ NEXT_PUBLIC_API_HOST: eth-sepolia.k8s-dev.blockscout.com
+ NEXT_PUBLIC_STATS_API_HOST: https://stats-sepolia.k8s-dev.blockscout.com/
+ NEXT_PUBLIC_VISUALIZE_API_HOST: http://visualizer-svc.visualizer-testing.svc.cluster.local/
+ 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
+ NEXT_PUBLIC_NAME_SERVICE_API_HOST: https://bens-rs-test.k8s-dev.blockscout.com
+ NEXT_PUBLIC_METADATA_SERVICE_API_HOST: https://metadata-test.k8s-dev.blockscout.com
+ NEXT_PUBLIC_AUTH_URL: https://blockscout-main.k8s-dev.blockscout.com
+ NEXT_PUBLIC_LOGOUT_URL: https://blockscoutcom.us.auth0.com/v2/logout
+ NEXT_PUBLIC_HOMEPAGE_CHARTS: "['daily_txs','coin_price','market_cap']"
+ NEXT_PUBLIC_NETWORK_RPC_URL: https://eth-sepolia.public.blastapi.io
+ 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','logo':'https://github.com/blockscout/frontend-configs/blob/main/configs/explorer-logos/etherscan.png?raw=true','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}]"
+ NEXT_PUBLIC_GRAPHIQL_TRANSACTION: 0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d
+ NEXT_PUBLIC_WEB3_WALLETS: "['token_pocket','coinbase','metamask']"
+ NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE: gradient_avatar
+ NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED: true
+ NEXT_PUBLIC_USE_NEXT_JS_PROXY: true
+ NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES: "[{'name':'LooksRare','collection_url':'https://goerli.looksrare.org/collections/{hash}','instance_url':'https://goerli.looksrare.org/collections/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/looks-rare.png'}]"
+ NEXT_PUBLIC_HAS_USER_OPS: true
+ NEXT_PUBLIC_CONTRACT_CODE_IDES: "[{'title':'Remix IDE','url':'https://remix.blockscout.com/?address={hash}&blockscout=eth-goerli.blockscout.com','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]"
+ NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER: blockscout
+ NEXT_PUBLIC_HAS_CONTRACT_AUDIT_REPORTS: true
+ NEXT_PUBLIC_AD_BANNER_PROVIDER: slise
+ NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED: true
+ NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES: "['/apps']"
+ PROMETHEUS_METRICS_ENABLED: true
+ NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED: true
+ NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED: true
+ envFromSecret:
+ NEXT_PUBLIC_AUTH0_CLIENT_ID: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_AUTH0_CLIENT_ID
+ NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID
+ NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID
+ NEXT_PUBLIC_GROWTH_BOOK_CLIENT_KEY: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_GROWTH_BOOK_CLIENT_KEY
+ NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN
+ NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY: ref+vault://deployment-values/blockscout/eth-sepolia/testnet?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/RE_CAPTCHA_CLIENT_KEY
+ NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN
diff --git a/explorer/frontend/docs/BUILD-TIME_ENVS.md b/explorer/frontend/docs/BUILD-TIME_ENVS.md
new file mode 100644
index 000000000..6ecaa5398
--- /dev/null
+++ b/explorer/frontend/docs/BUILD-TIME_ENVS.md
@@ -0,0 +1,10 @@
+# Build-time environment variables
+
+These variables are passed to the app during the image build process. They cannot be re-defined during the run-time.
+
+| Variable | Type | Description | Optional | Example value |
+| --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_GIT_COMMIT_SHA | `string` | SHA of the latest commit in the branch from which image is built | false | `29d0613e` |
+| NEXT_PUBLIC_GIT_TAG | `string` | Git tag of the latest commit in the branch from which image is built | true | `v1.0.0` |
+| NEXT_OPEN_TELEMETRY_ENABLED | `boolean` | Enables OpenTelemetry SDK | true | `true` |
+| NEXT_PUBLIC_ICON_SPRITE_HASH | `string` | Hash post-fix of the SVG sprite file (generated automatically during the sprite build) | `08be4b10` | `true` |
diff --git a/explorer/frontend/docs/CONTRIBUTING.md b/explorer/frontend/docs/CONTRIBUTING.md
new file mode 100644
index 000000000..0897bcf31
--- /dev/null
+++ b/explorer/frontend/docs/CONTRIBUTING.md
@@ -0,0 +1,219 @@
+# Contribution guide
+
+Thanks for showing interest to contribute to Blockscout. The following steps will get you up and running.
+
+
+
+## Our guidelines: what we are looking for
+
+We welcome contributions that enhance the project and improve the overall quality of our codebase. While we appreciate the effort that goes into making contributions, we kindly ask that contributors focus on the following types of changes:
+- **Feature Enhancements:** Substantial improvements or new features that add significant value to the project.
+- **Bug Fixes:** Fixes for known bugs or issues that impact functionality.
+- **Documentation Improvements:** Comprehensive updates to documentation that clarify usage, installation, or project structure.
+- **Performance Improvements:** Changes that enhance the performance or efficiency of the application.
+
+Please note that we accept contributions for newly submitted issues or those labeled "Available for contribution" - all other issues are reserved for the core team of the project.
+
+
+
+## Project setup
+
+1. Fork the repo by clicking Fork button at the top of the repo main page and name it appropriately
+
+2. Clone your fork locally
+ ```sh
+ git clone https://github.com//.git
+ cd
+ ```
+
+3. Make sure you're running Node.js 20+ and NPM 10+; if not, upgrade it accordingly, for example using [nvm](https://github.com/nvm-sh/nvm).
+ ```sh
+ node -v
+ npm -v
+ ```
+
+4. Install dependencies
+ ```sh
+ yarn
+ ```
+
+
+
+## Toolkit
+
+We are using following technology stack in the project
+- [Yarn](https://yarnpkg.com/) as package manager
+- [ReactJS](https://reactjs.org/) as UI library
+- [Next.js](https://nextjs.org/) as application framework
+- [Chakra](https://chakra-ui.com/) as component library; our theme customization can be found in `/theme` folder
+- [TanStack Query](https://tanstack.com/query/v4/docs/react/overview/) for fetching, caching and updating data from the API
+- [Jest](https://jestjs.io/) as JavaScript testing framework
+- [Playwright](https://playwright.dev/) as a tool for components visual testing
+
+And of course our premier language is [Typescript](https://www.typescriptlang.org/).
+
+
+
+## Local development
+
+To develop locally, follow one of the two paths outlined below:
+
+A. Custom configuration:
+
+1. Create `.env.local` file in the root folder and include all required environment variables from the [list](./ENVS.md)
+2. Optionally, clone `.env.example` and name it `.env.secrets`. Fill it with necessary secrets for integrating with [external services](./ENVS.md#external-services-configuration). Include only secrets you need.
+3. Use `yarn dev` command to start the Dev Server.
+4. Open your browser and navigate to the URL provided in the command line output (by default, it is `http://localhost:3000`).
+
+B. Pre-defined configuration:
+
+1. Optionally, clone `.env.example` file into `configs/envs/.env.secrets`. Fill it with necessary secrets for integrating with [external services](./ENVS.md#external-services-configuration). Include only secrets your need.
+2. Choose one of the predefined configurations located in the `/configs/envs` folder.
+3. Start your local Dev Server using the `yarn dev:preset ` command.
+4. Open your browser and navigate to the URL provided in the command line output (by default, it is `http://localhost:3000`).
+
+
+
+
+## Adding new dependencies
+For all types of dependencies:
+- **Do not add** a dependency if the desired functionality is easily implementable
+- If adding a dependency is necessary, please be sure that it is well-maintained and trustworthy
+
+
+
+## Adding new ENV variable
+
+*Note*, if the variable should be exposed to the browser don't forget to add prefix `NEXT_PUBLIC_` to its name.
+
+These are the steps that you have to follow to make everything work:
+1. First and foremost, document variable in the [/docs/ENVS.md](./ENVS.md) file; provide short description, its expected type, requirement flag, default and example value; **do not skip this step** otherwise the app will not receive variable value at run-time
+2. Make sure that you have added a property to React app config (`configs/app/index.ts`) in appropriate section that is associated with this variable; do not use ENV variable values directly in the application code; decide where this variable belongs to and place it under the certain section:
+ - `app` - the front-end app itself
+ - `api` - the main API configuration
+ - `chain` - the Blockchain parameters
+ - `UI` - the app UI customization
+ - `meta` - SEO and meta-tags customization
+ - `features` - the particular feature of the app
+ - `services` - some 3rd party service integration which is not related to one particular feature
+3. If a new variable is meant to store the URL of an external API service, remember to include its value in the Content-Security-Policy document header. Refer to `nextjs/csp/policies/app.ts` for details.
+4. For local development purposes add the variable with its appropriate values to pre-defined ENV configs `configs/envs` where it is needed
+5. Add the variable to CI configs where it is needed
+ - `deploy/values/review/values.yaml.gotmpl` - review development environment
+ - `deploy/values/review-l2/values.yaml.gotmpl` - review development environment for L2 networks
+6. If your variable is meant to receive a link to some external resource (image or JSON-config file), extend the array `ASSETS_ENVS` in `deploy/scripts/download_assets.sh` with your variable name
+7. Add validation schema for the new variable into the file `deploy/tools/envs-validator/schema.ts`
+8. Check if modified validation schema is valid by doing the following steps:
+ - change your current directory to `deploy/tools/envs-validator`
+ - install deps with `yarn` command
+ - add your variable into `./test/.env.base` test preset or create a new test preset if needed
+ - if your variable contains a link to the external JSON config file:
+ - add example of file content into `./test/assets` directory; the file name should be constructed by stripping away prefix `NEXT_PUBLIC_` and postfix `_URL` if any, and converting the remaining string to lowercase (for example, `NEXT_PUBLIC_MARKETPLACE_CONFIG_URL` will become `marketplace_config.json`)
+ - in the main script `index.ts` extend array `envsWithJsonConfig` with your variable name
+ - run `yarn test` command to see the validation result
+9. Don't forget to mention in the PR notes that new ENV variable was added
+
+
+
+## Writing & Running Tests
+
+Every feature or bugfix should be accompanied by tests, either unit tests or component visual tests, or both, except from trivial fixes (for example, typo fix). All commands for running tests you can find [below](./CONTRIBUTING.md#command-list).
+
+### Jest unit tests
+
+If your changes are only related to the logic of the app and not to its visual presentation, then try to write unit tests using [Jest](https://jestjs.io/) framework and [React Testing Library](https://testing-library.com/docs/react-testing-library/intro/). In general these tests are "cheaper" and faster than Playwright ones. Use them for testing your utilities and React hooks, as well as the whole components logic.
+
+Place your test suites in `.test.ts` or `.test.tsx` files. You can find or add some mocks or other helpful utilities for these tests purposes in the `/jest` folder.
+
+*Note*, that we are using custom renderer and wrapper in all tests for React components, so please do not import package `@testing-library/react` directly in your test suites, instead use imports from `jest/lib` utility.
+
+### Playwright components tests
+
+For changes associated with the UI itself write components visual tests using [Playwright](https://playwright.dev/) framework and its *experimental* [Components test library](https://playwright.dev/docs/test-components). Please be aware of known [issues and limitations](https://playwright.dev/docs/test-components#known-issues-and-limitations) of this library.
+
+Your tests files should have `.pw.tsx` extension. All configs, mocks, fixtures and other utilities for these tests live in `/playwright` folder.
+
+We have 3 pre-configured projects. You can run your test with the desired project by simply adding its [tag](https://playwright.dev/docs/test-annotations#tag-tests) to the test name:
+- `default` - default project for all test, uses desktop Chrome desktop device; don't need to specify its tag, instead use `-@default` tag to skip test run with this project
+- `mobile` - project for testing on mobile devices, uses Safari mobile browser; add tag `+@mobile` to run test with this project
+- `dark-color-mode` - project for testing app in the dark color mode, uses desktop Chrome desktop device with forced dark color mode; add tag `+@dark-mode` to run test with this project.
+
+*Note* that, since we are developing not on the same operating system as our CI system, we have to use Docker to generate or update the screenshots. In order to do that use `yarn test:pw:docker --update-snapshots` command. Please **do not commit** any screenshots generated via `yarn test:pw:local` command, their associated tests will fail in the CI run.
+
+
+
+## Making a Pull Request
+
+### Steps to PR
+
+1. Make sure that you fork and clone repo; check if the main branch has all recent changes from the original repo
+
+ > Tip: Keep your `main` branch pointing at the original repository and make pull
+ > requests from branches on your fork. To do this, run:
+ >
+ > ```
+ > git remote add upstream https://github.com/blockscout/frontend.git
+ > git fetch upstream
+ > git branch --set-upstream-to=upstream/main main
+ > ```
+ >
+ > This will add the original repository as a "remote" called "upstream," Then
+ > fetch the git information from that remote, then set your local `main` branch
+ > to use the upstream main branch whenever you run `git pull`. Then you can make
+ > all of your pull request branches based on this `main` branch. Whenever you
+ > want to update your version of `main`, do a regular `git pull`.
+
+2. Create a branch for your PR with `git checkout -b `; we do not follow any branch name convention just yet
+3. Commit your changes. Commits should be one logical change that still allows all tests to pass. Prefer smaller commits if there could be two levels of logic grouping. The goal is to allow contributors in the future (including your future self) to determine your reasoning for making changes and to allow them to cherry-pick, patch or port those changes in isolation to other branches or forks. Again, there is no strict commit message convention, but make sure that it clear and fully describes all changes that were made
+4. If during your PR you reveal a pre-existing bug, try to isolate the bug and fix it on an independent branch and PR it first
+5. Where possible, please provide unit tests that demonstrate new functionality or bug fix is working
+
+### Opening PR and getting it accepted
+
+1. Push your changes and create a Pull Request. If you are still working on the task, please use "Draft Pull Request" option, so we know that it is not ready yet. In addition, you can add label "skip checks" to your PR, so all CI checks will not be triggered.
+2. Once you finish your work, remove label "skip checks" from PR, if it was added before, and publish PR if it was in the draft state
+3. Make sure that all code checks and tests are successfully passed
+4. Add description to your Pull Request and link an existing issue(s) that it is fixing
+5. Request review from one or all core team members: @tom2drum, @isstuev. Our core team is committed to reviewing patches in a timely manner.
+6. After code review is done, we merge pull requests by squashing all commits and editing the commit message if necessary using the GitHub user interface.
+
+*Note*, if you Pull Request contains any changes that are not backwards compatible with the previous versions of the app, please specify them in PR description and add label ["breaking changes"](https://github.com/blockscout/frontend/labels/breaking%20changes) to it.
+
+
+
+## Commands list
+
+| Command | Description |
+| --- | --- |
+| **Running and building** |
+| `yarn dev` | run local Dev Server with user's configuration |
+| `yarn dev:preset ` | run local Dev Server with predefined configuration |
+| `yarn build:docker` | build a docker image locally |
+| `yarn start:docker:local` | start an application from previously built local docker image with user's configuration |
+| `yarn start:docker:preset ` | start an application from previously built local docker image with predefined configuration |
+| **Linting and formatting** |
+| `yarn lint:eslint` | lint project files with ESLint |
+| `yarn lint:eslint:fix` | lint project files with ESLint and automatically fix problems |
+| `yarn lint:tsc` | compile project typescript files using TypeScript Compiler |
+| `yarn svg:format` | format and optimize SVG icons in the `/icons` folder using SVGO tool |
+| `yarn svg:build-sprite` | build SVG icons sprite |
+| **Testing** |
+| `yarn test:jest` | run all Jest unit tests |
+| `yarn test:jest:watch` | run all Jest unit tests in watch mode |
+| `yarn test:pw:local` | run Playwright component tests locally |
+| `yarn test:pw:docker` | run Playwright component tests in docker container |
+| `yarn test:pw:ci` | run Playwright component tests in CI |
+
+
+
+## Tips & Tricks
+
+### Code Editor
+
+#### VSCode
+
+There are some predefined tasks for all commands described above. You can see the full list by pressing cmd + shift + P and using command `Task: Run task`
+
+Also there is a Jest test launch configuration for debugging and running current test file in the watch mode.
+
+And you may find the Dev Container setup useful too.
diff --git a/explorer/frontend/docs/CUSTOM_BUILD.md b/explorer/frontend/docs/CUSTOM_BUILD.md
new file mode 100644
index 000000000..9142e1284
--- /dev/null
+++ b/explorer/frontend/docs/CUSTOM_BUILD.md
@@ -0,0 +1,10 @@
+# Building and running your own docker image
+
+You are free to clone the repo and make any changes to the application code that you want, adding your own customization and features. After that you can build a docker image by running `yarn build:docker` or alternatively run `docker build` and pass your own args that is necessary.
+
+For running app container from freshly built image do
+```sh
+docker run -p 3000:3000 --env-file
+```
+
+*Disclaimer* Do not try to generate production build of the app on your local machine (outside the docker). The app will not work as you would expect.
diff --git a/explorer/frontend/docs/DEPRECATED_ENVS.md b/explorer/frontend/docs/DEPRECATED_ENVS.md
new file mode 100644
index 000000000..171df270f
--- /dev/null
+++ b/explorer/frontend/docs/DEPRECATED_ENVS.md
@@ -0,0 +1,14 @@
+# Deprecated environment variables
+
+| Variable | Type | Description | Compulsoriness | Default value | Example value | Introduced in version | Deprecated in version | Comment |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY | `string` | RealFaviconGenerator [API key](https://realfavicongenerator.net/api/) | Required | - | `` | v1.11.0 | v1.16.0 | Replaced FAVICON_GENERATOR_API_KEY |
+| FAVICON_GENERATOR_API_KEY | `string` | RealFaviconGenerator [API key](https://realfavicongenerator.net/api/) | Required | - | `` | v1.16.0+ | v1.37.0 | We don't use RealFaviconGenerator anymore |
+| NEXT_PUBLIC_IS_OPTIMISTIC_L2_NETWORK | `boolean` | Set to true for optimistic L2 solutions | Required | - | `true` | v1.17.0 | v1.24.0 | Replaced by NEXT_PUBLIC_ROLLUP_TYPE |
+| NEXT_PUBLIC_IS_ZKEVM_L2_NETWORK | `boolean` | Set to true for zkevm L2 solutions | Required | - | `true` | v1.17.0 | v1.24.0 | Replaced by NEXT_PUBLIC_ROLLUP_TYPE |
+| NEXT_PUBLIC_OPTIMISTIC_L2_WITHDRAWAL_URL | `string` | URL for optimistic L2 -> L1 withdrawals | Required | - | `https://app.optimism.io/bridge/withdraw` | v1.17.0 | v1.24.0 | Renamed to NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL |
+| NEXT_PUBLIC_L1_BASE_URL | `string` | Blockscout base URL for L1 network | Required | - | `'http://eth-goerli.blockscout.com'` | - | v1.24.0 | Renamed to NEXT_PUBLIC_ROLLUP_L1_BASE_URL |
+| NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER | `boolean` | Set to false if network doesn't have gas tracker | - | `true` | `false` | - | v1.25.0 | Replaced by NEXT_PUBLIC_GAS_TRACKER_ENABLED |
+| NEXT_PUBLIC_NETWORK_GOVERNANCE_TOKEN_SYMBOL | `string` | Network governance token symbol | - | - | `GNO` | v1.12.0 | v1.29.0 | Replaced by NEXT_PUBLIC_NETWORK_SECONDARY_COIN_SYMBOL |
+| NEXT_PUBLIC_SWAP_BUTTON_URL | `string` | Application ID in the marketplace or website URL | - | - | `uniswap` | v1.24.0 | v1.31.0 | Replaced by NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS |
+| NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME | `boolean` | Set to false if average block time is useless for the network | - | `true` | `false` | v1.0.x+ | v1.35.0 | Replaced by NEXT_PUBLIC_HOMEPAGE_STATS |
diff --git a/explorer/frontend/docs/ENVS.md b/explorer/frontend/docs/ENVS.md
new file mode 100644
index 000000000..a39057845
--- /dev/null
+++ b/explorer/frontend/docs/ENVS.md
@@ -0,0 +1,919 @@
+# Run-time environment variables
+
+The app instance can be customized by passing the following variables to the Node.js environment at runtime. Some of these variables have been deprecated, and their full list can be found in the [file](./DEPRECATED_ENVS.md).
+
+## Read before you run the app
+
+### Variables compulsoriness
+Please note that in the tables below, the "Compulsoriness" column indicates whether the variable is required for starting up the application, except for the "App Features" section. All features are optional by definition; therefore, the "Compulsoriness" column indicates whether a certain variable is required or optional only within the context of that feature, not for the entire application.
+
+### Disclaimer about using variables
+Please be aware that all environment variables prefixed with `NEXT_PUBLIC_` will be exposed to the browser. So any user can obtain its values. Make sure that for all 3rd-party services keys (e.g., Auth0, WalletConnect, etc.) in the services administration panel you have created a whitelist of allowed origins and have added your app domain into it. That will help you prevent using your key by unauthorized app, if someone gets its value.
+
+### Note about escaping variables values
+All json-like values should be single-quoted. If it contains a hash (`#`) or a dollar-sign (`$`) the whole value should be wrapped in single quotes as well (see `dotenv` [readme](https://github.com/bkeepers/dotenv#variable-substitution) for the reference)
+
+
+
+## Table of contents
+- [App configuration](ENVS.md#app-configuration)
+- [Blockchain parameters](ENVS.md#blockchain-parameters)
+- [API configuration](ENVS.md#api-configuration)
+- [UI configuration](ENVS.md#ui-configuration)
+ - [Homepage](ENVS.md#homepage)
+ - [Navigation](ENVS.md#navigation)
+ - [Footer](ENVS.md#footer)
+ - [Favicon](ENVS.md#favicon)
+ - [Meta](ENVS.md#meta)
+ - [Views](ENVS.md#views)
+ - [Block](ENVS.md#block-views)
+ - [Address](ENVS.md#address-views)
+ - [Transaction](ENVS.md#transaction-views)
+ - [NFT](ENVS.md#nft-views)
+ - [Misc](ENVS.md#misc)
+- [App features](ENVS.md#app-features)
+ - [My account](ENVS.md#my-account)
+ - [Gas tracker](ENVS.md#gas-tracker)
+ - [Advanced filter](ENVS.md#advanced-filter)
+ - [Address verification](ENVS.md#address-verification-in-my-account) in "My account"
+ - [Blockchain interaction](ENVS.md#blockchain-interaction-writing-to-contract-etc) (writing to contract, etc.)
+ - [Banner ads](ENVS.md#banner-ads)
+ - [Text ads](ENVS.md#text-ads)
+ - [Beacon chain](ENVS.md#beacon-chain)
+ - [User operations](ENVS.md#user-operations-erc-4337)
+ - [Rollup chain](ENVS.md#rollup-chain)
+ - [Export data to CSV file](ENVS.md#export-data-to-csv-file)
+ - [Google analytics](ENVS.md#google-analytics)
+ - [Mixpanel analytics](ENVS.md#mixpanel-analytics)
+ - [GrowthBook feature flagging and A/B testing](ENVS.md#growthbook-feature-flagging-and-ab-testing)
+ - [GraphQL API documentation](ENVS.md#graphql-api-documentation)
+ - [REST API documentation](ENVS.md#rest-api-documentation)
+ - [Marketplace](ENVS.md#marketplace)
+ - [Solidity to UML diagrams](ENVS.md#solidity-to-uml-diagrams)
+ - [Blockchain statistics](ENVS.md#blockchain-statistics)
+ - [Web3 wallet integration](ENVS.md#web3-wallet-integration-add-token-or-network-to-the-wallet) (add token or network to the wallet)
+ - [Transaction interpretation](ENVS.md#transaction-interpretation)
+ - [Verified tokens info](ENVS.md#verified-tokens-info)
+ - [Name service integration](ENVS.md#name-service-integration)
+ - [Metadata service integration](ENVS.md#metadata-service-integration)
+ - [Public tag submission](ENVS.md#public-tag-submission)
+ - [Data availability](ENVS.md#data-availability)
+ - [Bridged tokens](ENVS.md#bridged-tokens)
+ - [Safe{Core} address tags](ENVS.md#safecore-address-tags)
+ - [Address profile API](ENVS.md#address-profile-api)
+ - [Address XStar XHS score](ENVS.md#address-xstar-xhs-score)
+ - [SUAVE chain](ENVS.md#suave-chain)
+ - [MetaSuites extension](ENVS.md#metasuites-extension)
+ - [Validators list](ENVS.md#validators-list)
+ - [Sentry error monitoring](ENVS.md#sentry-error-monitoring)
+ - [Rollbar error monitoring](ENVS.md#rollbar-error-monitoring)
+ - [OpenTelemetry](ENVS.md#opentelemetry)
+ - [DeFi dropdown](ENVS.md#defi-dropdown)
+ - [Multichain balance button](ENVS.md#multichain-balance-button)
+ - [Get gas button](ENVS.md#get-gas-button)
+ - [Save on gas with GasHawk](ENVS.md#save-on-gas-with-gashawk)
+ - [Rewards service API](ENVS.md#rewards-service-api)
+ - [DEX pools](ENVS.md#dex-pools)
+- [3rd party services configuration](ENVS.md#external-services-configuration)
+
+
+
+## App configuration
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_APP_PROTOCOL | `http \| https` | App url schema | - | `https` | `http` | v1.0.x+ |
+| NEXT_PUBLIC_APP_HOST | `string` | App host | Required | - | `blockscout.com` | v1.0.x+ |
+| NEXT_PUBLIC_APP_PORT | `number` | Port where app is running | - | `3000` | `3001` | v1.0.x+ |
+| NEXT_PUBLIC_APP_ENV | `string` | App env (e.g development, staging, production, etc.). | - | `production` | `staging` | v1.0.x+ |
+| NEXT_PUBLIC_APP_INSTANCE | `string` | Name of app instance. Used for app monitoring purposes. If not provided, it will be constructed from `NEXT_PUBLIC_APP_HOST` | - | - | `wonderful_kepler` | v1.0.x+ |
+| NEXT_PUBLIC_USE_NEXT_JS_PROXY | `boolean` | Tells the app to proxy all APIs request through the NextJS app. **We strongly advise not to use it in the production environment**, since it can lead to performance issues of the NodeJS server | - | `false` | `true` | v1.8.0+ |
+
+
+
+## Blockchain parameters
+
+*Note!* The `NEXT_PUBLIC_NETWORK_CURRENCY` variables represent the blockchain's native token used for paying transaction fees. `NEXT_PUBLIC_NETWORK_SECONDARY_COIN` variables refer to tokens like protocol-specific tokens (e.g., OP token on Optimism chain) or governance tokens (e.g., GNO on Gnosis chain).
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_NETWORK_NAME | `string` | Displayed name of the network | Required | - | `Gnosis Chain` | v1.0.x+ |
+| NEXT_PUBLIC_NETWORK_SHORT_NAME | `string` | Used for SEO attributes (e.g, page description) | - | - | `OoG` | v1.0.x+ |
+| NEXT_PUBLIC_NETWORK_ID | `number` | Chain id, see [https://chainlist.org](https://chainlist.org) for the reference | Required | - | `99` | v1.0.x+ |
+| NEXT_PUBLIC_NETWORK_RPC_URL | `string \| Array` | Chain public RPC server url, see [https://chainlist.org](https://chainlist.org) for the reference. Can contain a single string value, or an array of urls. | - | - | `https://core.poa.network` | v1.0.x+ |
+| NEXT_PUBLIC_NETWORK_CURRENCY_NAME | `string` | Network currency name | - | - | `Ether` | v1.0.x+ |
+| NEXT_PUBLIC_NETWORK_CURRENCY_WEI_NAME | `string` | Name of network currency subdenomination | - | `wei` | `duck` | v1.23.0+ |
+| NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL | `string` | Network currency symbol | - | - | `ETH` | v1.0.x+ |
+| NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS | `string` | Network currency decimals | - | `18` | `6` | v1.0.x+ |
+| NEXT_PUBLIC_NETWORK_SECONDARY_COIN_SYMBOL | `string` | Network secondary coin symbol. | - | - | `GNO` | v1.29.0+ |
+| NEXT_PUBLIC_NETWORK_MULTIPLE_GAS_CURRENCIES | `boolean` | Set to `true` for networks where users can pay transaction fees in either the native coin or ERC-20 tokens. | - | `false` | `true` | v1.33.0+ |
+| NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE | `validation` \| `mining` | Verification type in the network. Irrelevant for Arbitrum (verification type is always `posting`) and ZkEvm (verification type is always `sequencing`) L2s | - | `mining` | `validation` | v1.0.x+ |
+| NEXT_PUBLIC_NETWORK_TOKEN_STANDARD_NAME | `string` | Name of the standard for creating tokens | - | `ERC` | `BEP` | v1.31.0+ |
+| NEXT_PUBLIC_IS_TESTNET | `boolean`| Set to true if network is testnet | - | `false` | `true` | v1.0.x+ |
+
+
+
+## API configuration
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_API_PROTOCOL | `http \| https` | Main API protocol | - | `https` | `http` | v1.0.x+ |
+| NEXT_PUBLIC_API_HOST | `string` | Main API host | Required | - | `blockscout.com` | v1.0.x+ |
+| NEXT_PUBLIC_API_PORT | `number` | Port where API is running on the host | - | - | `3001` | v1.0.x+ |
+| NEXT_PUBLIC_API_BASE_PATH | `string` | Base path for Main API endpoint url | - | - | `/poa/core` | v1.0.x+ |
+| NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL | `ws \| wss` | Main API websocket protocol | - | `wss` | `ws` | v1.0.x+ |
+
+
+
+## UI configuration
+
+### Homepage
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_HOMEPAGE_CHARTS | `Array<'daily_txs' \| 'daily_operational_txs' \| 'coin_price' \| 'secondary_coin_price' \| 'market_cap' \| 'tvl'>` | List of charts displayed on the home page | - | - | `['daily_txs','coin_price','market_cap']` | v1.0.x+ |
+| NEXT_PUBLIC_HOMEPAGE_STATS | `Array<'latest_batch' \| 'total_blocks' \| 'average_block_time' \| 'total_txs' \| 'total_operational_txs' \| 'latest_l1_state_batch' \| 'wallet_addresses' \| 'gas_tracker' \| 'btc_locked' \| 'current_epoch'>` | List of stats widgets displayed on the home page | - | For zkSync, zkEvm and Arbitrum rollups: `['latest_batch','average_block_time','total_txs','wallet_addresses','gas_tracker']`, for other cases: `['total_blocks','average_block_time','total_txs','wallet_addresses','gas_tracker']` | `['total_blocks','total_txs','wallet_addresses']` | v1.35.x+ |
+| NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR | `string` | Text color of the hero plate on the homepage (escape "#" symbol if you use HEX color codes or use rgba-value instead). **DEPRECATED** _Use `NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG` instead_ | - | `white` | `\#DCFE76` | v1.0.x+ |
+| NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND | `string` | Background css value for hero plate on the homepage (escape "#" symbol if you use HEX color codes or use rgba-value instead). **DEPRECATED** _Use `NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG` instead_ | - | `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)` | v1.1.0+ |
+| NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG | `HeroBannerConfig`, see details [below](#hero-banner-configuration-properties) | Configuration of hero banner appearance. | - | - | See [below](#hero-banner-configuration-properties) | v1.35.0+ |
+
+#### Hero banner configuration properties
+
+_Note_ Here, all values are arrays of up to two strings. The first string represents the value for the light color mode, and the second string represents the value for the dark color mode. If the array contains only one string, it will be used for both color modes.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value |
+| --- | --- | --- | --- | --- | --- |
+| background | `[string, string]` | Banner background (could be a solid color, gradient or picture). The string should be a valid `background` CSS property value. | - | `['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)']` | `['lightpink','no-repeat bottom 20% right 0px/100% url(https://placekitten/1400/200)']` |
+| text_color | `[string, string]` | Banner text background. The string should be a valid `color` CSS property value. | - | `['white']` | `['lightpink','#DCFE76']` |
+| border | `[string, string]` | Banner border. The string should be a valid `border` CSS property value. | - | - | `['1px solid yellow','4px dashed #DCFE76']` |
+| button | `Partial>` | The button on the banner. It has three possible states: `_default`, `_hover`, and `_selected`. The `_selected` state reflects when the user is logged in or their wallet is connected to the app. | - | - | `{'_default':{'background':['deeppink'],'text_color':['white']}}` |
+
+
+
+### Navigation
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_NETWORK_LOGO | `string` | Network logo; if not provided, placeholder will be shown; *Note* the logo height should be 24px and width less than 120px | - | - | `https://placekitten.com/240/40` | v1.0.x+ |
+| NEXT_PUBLIC_NETWORK_LOGO_DARK | `string` | Network logo for dark color mode; if not provided, **inverted** regular logo will be used instead | - | - | `https://placekitten.com/240/40` | v1.0.x+ |
+| NEXT_PUBLIC_NETWORK_ICON | `string` | Network icon; used as a replacement for regular network logo when nav bar is collapsed; if not provided, placeholder will be shown; *Note* the icon size should be at least 60px by 60px | - | - | `https://placekitten.com/60/60` | v1.0.x+ |
+| NEXT_PUBLIC_NETWORK_ICON_DARK | `string` | Network icon for dark color mode; if not provided, **inverted** regular icon will be used instead | - | - | `https://placekitten.com/60/60` | v1.0.x+ |
+| NEXT_PUBLIC_FEATURED_NETWORKS | `string` | URL of configuration file (`.json` format only) or file content string representation. It 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` \| `[{'title':'Astar(EVM)','url':'https://astar.blockscout.com/','group':'Mainnets','icon':'https://example.com/astar.svg'}]` | v1.0.x+ |
+| NEXT_PUBLIC_OTHER_LINKS | `Array<{url: string; text: string}>` | List of links for the "Other" navigation menu | - | - | `[{'url':'https://blockscout.com','text':'Blockscout'}]` | v1.0.x+ |
+| NEXT_PUBLIC_NAVIGATION_HIDDEN_LINKS | `Array` | List of external links hidden in the navigation. Supported ids are `eth_rpc_api`, `rpc_api` | - | - | `['eth_rpc_api']` | v1.16.0+ |
+| NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES | `Array` | List of menu item routes that should have a lightning label | - | - | `['/accounts']` | v1.31.0+ |
+| NEXT_PUBLIC_NAVIGATION_LAYOUT | `vertical \| horizontal` | Navigation menu layout type | - | `vertical` | `horizontal` | v1.32.0+ |
+
+#### Featured network configuration properties
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value |
+| --- | --- | --- | --- | --- | --- |
+| title | `string` | Displayed name of the network | Required | - | `Gnosis Chain` |
+| url | `string` | Network explorer main page url | Required | - | `https://blockscout.com/xdai/mainnet` |
+| group | `Mainnets \| Testnets \| Other` | Indicates in which tab network appears in the menu | Required | - | `Mainnets` |
+| icon | `string` | Network icon; if not provided, the common placeholder will be shown; *Note* that icon size should be at least 60px by 60px | - | - | `https://placekitten.com/60/60` |
+| isActive | `boolean` | Pass `true` if item should be shown as active in the menu | - | - | `true` |
+| invertIconInDarkMode | `boolean` | Pass `true` if icon colors should be inverted in dark mode | - | - | `true` |
+
+
+
+### Footer
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_FOOTER_LINKS | `string` | URL of configuration file (`.json` format only) or file content string representation. It contains list of link groups to be displayed in the footer. See [below](#footer-links-configuration-properties) list of available properties for particular group | - | - | `https://example.com/footer_links_config.json` \| `[{'title':'My chain','links':[{'text':'About','url':'https://example.com/about'},{'text':'Contacts','url':'https://example.com/contacts'}]}]` | v1.1.1+ |
+
+The app version shown in the footer is derived from build-time ENV variables `NEXT_PUBLIC_GIT_TAG` and `NEXT_PUBLIC_GIT_COMMIT_SHA` and cannot be overwritten at run-time.
+
+#### Footer links configuration properties
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value |
+| --- | --- | --- | --- | --- | --- |
+| title | `string` | Title of link group | Required | - | `Company` |
+| links | `Array<{'text':string;'url':string;}>` | list of links | Required | - | `[{'text':'Homepage','url':'https://www.blockscout.com'}]` |
+
+
+
+### Favicon
+
+By default, the app has generic favicon. You can override this behavior by providing the following variable. Hence, the favicon assets bundle will be generated at the container start time and will be used instead of default one.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| FAVICON_MASTER_URL | `string` | - | - | `NEXT_PUBLIC_NETWORK_ICON` | `https://placekitten.com/180/180` | v1.11.0+ |
+
+
+
+### Meta
+
+Settings for meta tags, OG tags and SEO
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_PROMOTE_BLOCKSCOUT_IN_TITLE | `boolean` | Set to `true` to promote Blockscout in meta and OG titles | - | `true` | `true` | v1.12.0+ |
+| NEXT_PUBLIC_OG_DESCRIPTION | `string` | Custom OG description | - | - | `Open-source block explorer by Blockscout. Search transactions, verify smart contracts, analyze addresses, and track network activity. Complete blockchain data and APIs for the %network_title% network.` | v1.12.0+ |
+| NEXT_PUBLIC_OG_IMAGE_URL | `string` | OG image url. Minimum image size is 200 x 20 pixels (recommended: 1200 x 600); maximum supported file size is 8 MB; 2:1 aspect ratio; supported formats: image/jpeg, image/gif, image/png | - | `static/og_placeholder.png` | `https://placekitten.com/1200/600` | v1.12.0+ |
+| NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED | `boolean` | Set to `true` to populate OG tags (title, description) with API data for social preview robot requests | - | `false` | `true` | v1.29.0+ |
+| NEXT_PUBLIC_SEO_ENHANCED_DATA_ENABLED | `boolean` | Set to `true` to pre-render page titles (e.g Token page) on the server side and inject page h1-tag to the markup before it is sent to the browser. | - | `false` | `true` | v1.30.0+ |
+
+
+
+### Views
+
+#### Block views
+
+| Variable | Type | Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_VIEWS_BLOCK_HIDDEN_FIELDS | `Array` | Array of the block fields ids that should be hidden. See below the list of the possible id values. | - | - | `'["burnt_fees","total_reward"]'` | v1.10.0+ |
+
+
+##### Block fields list
+| Id | Description |
+| --- | --- |
+| `base_fee` | Base fee |
+| `burnt_fees` | Burnt fees |
+| `total_reward` | Total block reward |
+| `nonce` | Block nonce |
+| `miner` | Address of block's miner or validator |
+| `L1_status` | Short interpretation of the batch lifecycle (applicable for Rollup chains) |
+| `batch` | Batch index (applicable for Rollup chains) |
+
+
+
+#### Address views
+
+| Variable | Type | Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE | `"github" \| "jazzicon" \| "gradient_avatar" \| "blockie" \| "nouns"` | Default style of address identicon appearance. Choose between [GitHub](https://github.blog/2013-08-14-identicons/), [Metamask Jazzicon](https://metamask.github.io/jazzicon/), [Gradient Avatar](https://github.com/varld/gradient-avatar), [Ethereum Blocky](https://mycryptohq.github.io/ethereum-blockies-base64/) and [Nouns](https://nouns.wtf) | - | `jazzicon` | `gradient_avatar` | v1.12.0+ |
+| NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT | `Array<"base16" \| "bech32">` | Displayed address format, could be either `base16` standard or [`bech32`](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#bech32) standard. If the array contains multiple values, the address format toggle will appear in the UI, allowing the user to switch between formats. The first item in the array will be the default format. | - | `'["base16"]'` | `'["bech32", "base16"]'` | v1.36.0+ |
+| NEXT_PUBLIC_VIEWS_ADDRESS_BECH_32_PREFIX | `string` | Human-readable prefix of `bech32` address format. | Required, if `NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT` contains "bech32" value | - | `duck` | v1.36.0+ |
+| NEXT_PUBLIC_VIEWS_ADDRESS_HIDDEN_VIEWS | `Array` | Address views that should not be displayed. See below the list of the possible id values. | - | - | `'["top_accounts"]'` | v1.15.0+ |
+| NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED | `boolean` | Set to `true` if SolidityScan reports are supported | - | - | `true` | v1.19.0+ |
+| NEXT_PUBLIC_VIEWS_CONTRACT_EXTRA_VERIFICATION_METHODS | `Array<'solidity-hardhat' \| 'solidity-foundry'>` | Pass an array of additional methods from which users can choose while verifying a smart contract. Both methods are available by default, pass `'none'` string to disable them all. | - | - | `['solidity-hardhat']` | v1.33.0+ |
+| NEXT_PUBLIC_VIEWS_CONTRACT_LANGUAGE_FILTERS | `Array<'solidity' \| 'vyper' \| 'yul' \| 'scilla'>` | Pass an array of contract languages that will be displayed as options in the filter on the verified contract page. | - | `['solidity','vyper','yul']` | `['solidity','vyper','yul','scilla']` | v1.37.0+ |
+
+##### Address views list
+| Id | Description |
+| --- | --- |
+| `top_accounts` | Top accounts |
+
+
+
+#### Transaction views
+
+| Variable | Type | Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_VIEWS_TX_HIDDEN_FIELDS | `Array` | Array of the transaction fields ids that should be hidden. See below the list of the possible id values. | - | - | `'["value","tx_fee"]'` | v1.15.0+ |
+| NEXT_PUBLIC_VIEWS_TX_ADDITIONAL_FIELDS | `Array` | Array of the additional fields ids that should be added to the transaction details. See below the list of the possible id values. | - | - | `'["fee_per_gas"]'` | v1.15.0+ |
+
+##### Transaction fields list
+| Id | Description |
+| --- | --- |
+| `value` | Sent value |
+| `fee_currency` | Fee currency |
+| `gas_price` | Price per unit of gas |
+| `tx_fee` | Total transaction fee |
+| `gas_fees` | Gas fees breakdown |
+| `burnt_fees` | Amount of native coin burnt for transaction |
+| `L1_status` | Short interpretation of the batch lifecycle (applicable for Rollup chains) |
+| `batch` | Batch index (applicable for Rollup chains) |
+
+##### Transaction additional fields list
+| Id | Description |
+| --- | --- |
+| `fee_per_gas` | Amount of total fee divided by total amount of gas used by transaction |
+
+
+
+#### Token views
+| Variable | Type | Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED | `boolean` | Show the "Hide scam tokens" toggle in the site settings dropdown. This option controls the visibility of tokens with a poor reputation in the search results. | - | `false` | `true` | v1.38.0+ |
+
+
+
+#### NFT views
+
+| Variable | Type | Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES | `Array` where `NftMarketplace` can have following [properties](#nft-marketplace-properties) | Used to build up links to NFT collections and NFT instances in external marketplaces. | - | - | `[{'name':'OpenSea','collection_url':'https://opensea.io/assets/ethereum/{hash}','instance_url':'https://opensea.io/assets/ethereum/{hash}/{id}','logo_url':'https://opensea.io/static/images/logos/opensea-logo.svg'}]` | v1.15.0+ |
+| NEXT_PUBLIC_HELIA_VERIFIED_FETCH_ENABLED | `boolean` | Indicates that the [Helia verified fetch](https://github.com/ipfs/helia-verified-fetch/tree/main/packages/verified-fetch) should be used for retrieving content of NFT assets (currently limited to images) directly from IPFS network using trustless gateways. | - | `true` | `false` | v1.37.0+ |
+
+##### NFT marketplace properties
+| Variable | Type| Description | Compulsoriness | Default value | Example value |
+| --- | --- | --- | --- | --- | --- |
+| name | `string` | Displayed name of the marketplace | Required | - | `OpenSea` |
+| collection_url | `string` | URL template for NFT collection | Required | - | `https://opensea.io/assets/ethereum/{hash}` |
+| instance_url | `string` | URL template for NFT instance | Required | - | `https://opensea.io/assets/ethereum/{hash}/{id}` |
+| logo_url | `string` | URL of marketplace logo | Required | - | `https://opensea.io/static/images/logos/opensea-logo.svg` |
+
+*Note* URL templates should contain placeholders of NFT hash (`{hash}`) and NFT id (`{id}`). This placeholders will be substituted with particular values for every collection or instance.
+
+
+
+### Misc
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_NETWORK_EXPLORERS | `Array` where `NetworkExplorer` can have following [properties](#network-explorer-configuration-properties) | Used to build up links to transactions, blocks, addresses in other chain explorers. | - | - | `[{'title':'Anyblock','baseUrl':'https://explorer.anyblock.tools','paths':{'tx':'/ethereum/poa/core/tx'}}]` | v1.0.x+ |
+| NEXT_PUBLIC_CONTRACT_CODE_IDES | `Array` where `ContractCodeIde` can have following [properties](#contract-code-ide-configuration-properties) | Used to build up links to IDEs with contract source code. | - | - | `[{'title':'Remix IDE','url':'https://remix.blockscout.com/?address={hash}&blockscout={domain}','icon_url':'https://example.com/icon.svg'}]` | v1.23.0+ |
+| NEXT_PUBLIC_HAS_CONTRACT_AUDIT_REPORTS | `boolean` | Set to `true` to enable Submit Audit form on the contract page | - | `false` | `true` | v1.25.0+ |
+| NEXT_PUBLIC_HIDE_INDEXING_ALERT_BLOCKS | `boolean` | Set to `true` to hide indexing alert in the page header about indexing chain's blocks | - | `false` | `true` | v1.17.0+ |
+| NEXT_PUBLIC_HIDE_INDEXING_ALERT_INT_TXS | `boolean` | Set to `true` to hide indexing alert in the page footer about indexing block's internal transactions | - | `false` | `true` | v1.17.0+ |
+| NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE | `string` | Used for displaying custom announcements or alerts in the header of the site. Could be a regular string or a HTML code. | - | - | `Hello world! 🤪` | v1.13.0+ |
+| NEXT_PUBLIC_COLOR_THEME_DEFAULT | `'light' \| 'dim' \| 'midnight' \| 'dark'` | Preferred color theme of the app | - | - | `midnight` | v1.30.0+ |
+| NEXT_PUBLIC_FONT_FAMILY_HEADING | `FontFamily`, see full description [below](#font-family-configuration-properties) | Special typeface to use in page headings (``, ``, etc.) | - | - | `{'name':'Montserrat','url':'https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap'}` | v1.35.0+ |
+| NEXT_PUBLIC_FONT_FAMILY_BODY | `FontFamily`, see full description [below](#font-family-configuration-properties) | Main typeface to use in page content elements. | - | - | `{'name':'Raleway','url':'https://fonts.googleapis.com/css2?family=Raleway:wght@400;500;600;700&display=swap'}` | v1.35.0+ |
+| NEXT_PUBLIC_MAX_CONTENT_WIDTH_ENABLED | `boolean` | Set to `true` to restrict the page content width on extra-large screens. | - | `true` | `false` | v1.34.1+ |
+
+#### Network explorer configuration properties
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value |
+| --- | --- | --- | --- | --- | --- |
+| logo | `string` | URL to explorer logo file. Should be at least 40x40. | - | - | `'https://foo.app/icon.png'` |
+| title | `string` | Displayed name of the explorer | Required | - | `Anyblock` |
+| baseUrl | `string` | Base url of the explorer | Required | - | `https://explorer.anyblock.tools` |
+| paths | `Record<'tx' \| 'block' \| 'address' \| 'token', string>` | Map of explorer entities and their paths | Required | - | `{'tx':'/ethereum/poa/core/tx'}` |
+
+*Note* The url of an entity will be constructed as `]>`, e.g `https://explorer.anyblock.tools/ethereum/poa/core/tx/`
+
+#### Contract code IDE configuration properties
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value |
+| --- | --- | --- | --- | --- | --- |
+| title | `string` | Displayed name of the IDE | Required | - | `Remix IDE` |
+| url | `string` | URL of the IDE with placeholders for contract hash (`{hash}`) and current domain (`{domain}`) | Required | - | `https://remix.blockscout.com/?address={hash}&blockscout={domain}` |
+| icon_url | `string` | URL of the IDE icon | Required | - | `https://example.com/icon.svg` |
+
+#### Font family configuration properties
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value |
+| --- | --- | --- | --- | --- | --- |
+| name | `string` | Font family name; used to define the `font-family` CSS property. | Required | - | `Montserrat` |
+| url | `string` | URL for external font. Ensure the font supports the following weights: 400, 500, 600, and 700. | Required | - | `https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap` |
+
+
+
+## App features
+
+*Note* The variables which are marked as required should be passed as described in order to enable the particular feature, but they are not required in the entire app context.
+
+### My account
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED | `boolean` | Set to true if network has account feature | Required | - | `true` | v1.0.x+ |
+| NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY | `boolean` | See [below](ENVS.md#google-recaptcha) | Required | - | `` | v1.0.x+ |
+| NEXT_PUBLIC_AUTH0_CLIENT_ID | `string` | **DEPRECATED** Client id for [Auth0](https://auth0.com/) provider | - | - | `` | v1.0.x+ |
+| NEXT_PUBLIC_AUTH_URL | `string` | **DEPRECATED** Account auth base url; it is used for building login URL (`${ NEXT_PUBLIC_AUTH_URL }/auth/auth0`) and logout return URL (`${ NEXT_PUBLIC_AUTH_URL }/auth/logout`); if not provided the base app URL will be used instead | - | - | `https://blockscout.com` | v1.0.x+ |
+| NEXT_PUBLIC_LOGOUT_URL | `string` | **DEPRECATED** Account logout url. Required if account is supported for the app instance. | - | - | `https://blockscoutcom.us.auth0.com/v2/logout` | v1.0.x+ |
+
+
+
+### Gas tracker
+
+This feature is **enabled by default**. To switch it off pass `NEXT_PUBLIC_GAS_TRACKER_ENABLED=false`.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_GAS_TRACKER_ENABLED | `boolean` | Set to true to enable "Gas tracker" in the app | Required | `true` | `false` | v1.25.0+ |
+| NEXT_PUBLIC_GAS_TRACKER_UNITS | Array<`usd` \| `gwei`> | Array of units for displaying gas prices on the Gas Tracker page, in the stats snippet on the Home page, and in the top bar. The first value in the array will take priority over the second one in all mentioned views. If only one value is provided, gas prices will be displayed only in that unit. | - | `[ 'usd', 'gwei' ]` | `[ 'gwei' ]` | v1.25.0+ |
+
+
+
+### Advanced filter
+
+This feature is **enabled by default**. To switch it off pass `NEXT_PUBLIC_ADVANCED_FILTER_ENABLED=false`.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_ADVANCED_FILTER_ENABLED | `boolean` | Set to true to enable "Advanced filter" page in the app | Required | `true` | `false` | v1.37.0+ |
+
+
+
+### Address verification in "My account"
+
+*Note* all ENV variables required for [My account](ENVS.md#my-account) feature should be passed alongside the following ones:
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_CONTRACT_INFO_API_HOST | `string` | Contract Info API endpoint url | Required | - | `https://contracts-info.services.blockscout.com` | v1.1.0+ |
+| NEXT_PUBLIC_ADMIN_SERVICE_API_HOST | `string` | Admin Service API endpoint url | Required | - | `https://admin-rs.services.blockscout.com` | v1.1.0+ |
+
+
+
+### Blockchain interaction (writing to contract, etc.)
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID | `string` | Project id for [WalletConnect](https://cloud.walletconnect.com/) integration | Required | - | `` | v1.0.x+ |
+| NEXT_PUBLIC_NETWORK_RPC_URL | `string` | See in [Blockchain parameters](ENVS.md#blockchain-parameters) section | Required | - | `https://core.poa.network` | v1.0.x+ |
+| NEXT_PUBLIC_NETWORK_NAME | `string` | See in [Blockchain parameters](ENVS.md#blockchain-parameters) section | Required | - | `Gnosis Chain` | v1.0.x+ |
+| NEXT_PUBLIC_NETWORK_ID | `number` | See in [Blockchain parameters](ENVS.md#blockchain-parameters) section | Required | - | `99` | v1.0.x+ |
+| NEXT_PUBLIC_NETWORK_CURRENCY_NAME | `string` | See in [Blockchain parameters](ENVS.md#blockchain-parameters) section | Required | - | `Ether` | v1.0.x+ |
+| NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL | `string` | See in [Blockchain parameters](ENVS.md#blockchain-parameters) section | Required | - | `ETH` | v1.0.x+ |
+| NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS | `string` | See in [Blockchain parameters](ENVS.md#blockchain-parameters) section | - | `18` | `6` | v1.0.x+ |
+
+
+
+### Banner ads
+
+This feature is **enabled by default** with the `slise` ads provider. To switch it off pass `NEXT_PUBLIC_AD_BANNER_PROVIDER=none`.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_AD_BANNER_PROVIDER | `slise` \| `adbutler` \| `coinzilla` \| `hype` \| `none` | Ads provider | - | `slise` | `coinzilla` | v1.0.x+ |
+| NEXT_PUBLIC_AD_BANNER_ADDITIONAL_PROVIDER | `adbutler` | Additional ads provider to mix with the main one | - | - | `adbutler` | v1.28.0+ |
+| NEXT_PUBLIC_AD_ADBUTLER_CONFIG_DESKTOP | `{ id: string; width: string; height: string }` | Placement config for desktop Adbutler banner | - | - | `{'id':'123456','width':'728','height':'90'}` | v1.3.0+ |
+| NEXT_PUBLIC_AD_ADBUTLER_CONFIG_MOBILE | `{ id: string; width: number; height: number }` | Placement config for mobile Adbutler banner | - | - | `{'id':'654321','width':'300','height':'100'}` | v1.3.0+ |
+
+
+
+### Text ads
+
+This feature is **enabled by default** with the `coinzilla` ads provider. To switch it off pass `NEXT_PUBLIC_AD_TEXT_PROVIDER=none`.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_AD_TEXT_PROVIDER | `coinzilla` \| `none` | Ads provider | - | `coinzilla` | `none` | v1.0.x+ |
+
+
+
+### Beacon chain
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_HAS_BEACON_CHAIN | `boolean` | Set to true for networks with the beacon chain | Required | - | `true` | v1.0.x+ |
+| NEXT_PUBLIC_BEACON_CHAIN_CURRENCY_SYMBOL | `string` | Beacon network currency symbol | - | `NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL` | `ETH` | v1.0.x+ |
+
+
+
+### User operations (ERC-4337)
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_HAS_USER_OPS | `boolean` | Set to true to show user operations related data and pages | - | - | `true` | v1.23.0+ |
+
+
+
+### Rollup chain
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_ROLLUP_TYPE | `'optimistic' \| 'arbitrum' \| 'shibarium' \| 'zkEvm' \| 'zkSync' \| 'scroll'` | Rollup chain type | Required | - | `'optimistic'` | v1.24.0+ |
+| NEXT_PUBLIC_ROLLUP_L1_BASE_URL | `string` | Blockscout base URL for L1 network. **DEPRECATED** _Use `NEXT_PUBLIC_ROLLUP_PARENT_CHAIN` instead_ | Required | - | `'http://eth-goerli.blockscout.com'` | v1.24.0+ |
+| NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL | `string` | URL for L2 -> L1 withdrawals (Optimistic stack only) | Required for `optimistic` rollups | - | `https://app.optimism.io/bridge/withdraw` | v1.24.0+ |
+| NEXT_PUBLIC_FAULT_PROOF_ENABLED | `boolean` | Set to `true` for chains with fault proof system enabled (Optimistic stack only) | - | - | `true` | v1.31.0+ |
+| NEXT_PUBLIC_HAS_MUD_FRAMEWORK | `boolean` | Set to `true` for instances that use MUD framework (Optimistic stack only) | - | - | `true` | v1.33.0+ |
+| NEXT_PUBLIC_INTEROP_ENABLED | `boolean` | Enables "Interop messages" page (Optimistic stack only) | - | `false` | `true` | v1.39.0+ |
+| NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS | `boolean` | Set to `true` to display "Latest blocks" widget instead of "Latest batches" on the home page | - | - | `true` | v1.36.0+ |
+| NEXT_PUBLIC_ROLLUP_OUTPUT_ROOTS_ENABLED | `boolean` | Enables "Output roots" page (Optimistic stack only) | - | `false` | `true` | v1.37.0+ |
+| NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME | `string` | Set to customize L1 transaction status labels in the UI (e.g., "Sent to "). This setting is applicable only for Arbitrum-based chains. **DEPRECATED** _Use `NEXT_PUBLIC_ROLLUP_PARENT_CHAIN` instead_ | - | - | `DuckChain` | v1.37.0+ |
+| NEXT_PUBLIC_ROLLUP_PARENT_CHAIN | `ParentChain`, see details [below](#parent-chain-configuration-properties) | Configuration parameters for the parent chain. | - | - | `{'baseUrl':'https://explorer.duckchain.io'}` | v1.38.0+ |
+| NEXT_PUBLIC_ROLLUP_DA_CELESTIA_NAMESPACE | `string` | Hex-string for creating a link to the transaction batch on the Seleneium explorer. "0x"-format and 60 symbol length. Available only for Arbitrum roll-ups. | - | - | `0x00000000000000000000000000000000000000ca1de12a9905be97beaf` | v1.38.0+ |
+| NEXT_PUBLIC_ROLLUP_DA_CELESTIA_CELENIUM_URL | `string` | URL for the Selenium explorer. It is used to create links to the Data Availability Blobs page. The URL should contain the full path without any search parameters related to the blob, as these will be constructed at runtime for each blob separately. Available only for Optimistic or Arbitrum roll-ups. | - | - | `https://mocha.celenium.io/blob` | v2.0.2+ |
+
+#### Parent chain configuration properties
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value |
+| --- | --- | --- | --- | --- | --- |
+| id | `number` | Chain id, see [https://chainlist.org](https://chainlist.org) for the reference. | - | - | `42` |
+| name | `string` | Displayed name of the chain. Set to customize L1 transaction status labels in the UI (e.g., "Sent to "). Currently, this setting is applicable only for Arbitrum-based chains. | - | - | `DuckChain` |
+| baseUrl | `string` | Base url of the chain explorer. | Required | - | `https://explorer.duckchain.io` |
+| rpcUrls | `Array` | Chain public RPC server urls, see [https://chainlist.org](https://chainlist.org) for the reference. | - | - | `['https://rpc.duckchain.io']` |
+| currency | `{ name: string; symbol: string; decimals: number; }` | Chain currency config. | - | - | `{ name: Quack, symbol: QUA, decimals: 18 }` |
+| isTestnet | `boolean` | Set to true if network is testnet. | - | - | `true` |
+
+
+
+
+### Export data to CSV file
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY | `string` | See [below](ENVS.md#google-recaptcha) | true | - | `` | v1.0.x+ |
+
+
+
+### Google analytics
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID | `string` | Property ID for [Google Analytics](https://analytics.google.com/) service | true | - | `UA-XXXXXX-X` | v1.0.x+ |
+
+
+
+### Mixpanel analytics
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN | `string` | Project token for [Mixpanel](https://mixpanel.com/) analytics service | true | - | `` | v1.1.0+ |
+
+
+
+### GrowthBook feature flagging and A/B testing
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_GROWTH_BOOK_CLIENT_KEY | `string` | Client SDK key for [GrowthBook](https://www.growthbook.io/) service | true | - | `` | v1.22.0+ |
+
+
+
+### GraphQL API documentation
+
+This feature is **always enabled**, but you can disable it by passing `none` value to `NEXT_PUBLIC_GRAPHIQL_TRANSACTION` variable.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_GRAPHIQL_TRANSACTION | `string` | Txn hash for default query at GraphQl playground page. Pass `none` to disable the feature. | - | - | `0x4a0ed8ddf751a7cb5297f827699117b0f6d21a0b2907594d300dc9fed75c7e62` | v1.0.x+ |
+
+
+
+### REST API documentation
+
+This feature is **always enabled**, but you can disable it by passing `none` value to `NEXT_PUBLIC_API_SPEC_URL` variable.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_API_SPEC_URL | `string` | Spec to be displayed on `/api-docs` page. Pass `none` to disable the feature. | - | `https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml` | `https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml` | v1.0.x+ |
+
+
+
+### Marketplace
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_MARKETPLACE_ENABLED | `boolean` | `true` means that the marketplace page will be enabled | Required | - | `true` | v1.24.1+ |
+| NEXT_PUBLIC_MARKETPLACE_CONFIG_URL | `string` | URL of configuration file (`.json` format only) which contains list of apps that will be shown on the marketplace page. See [below](#marketplace-app-configuration-properties) list of available properties for an app. Can be replaced with NEXT_PUBLIC_ADMIN_SERVICE_API_HOST | Required | - | `https://example.com/marketplace_config.json` | v1.0.x+ |
+| NEXT_PUBLIC_ADMIN_SERVICE_API_HOST | `string` | Admin Service API endpoint url. Can be used instead of NEXT_PUBLIC_MARKETPLACE_CONFIG_URL | - | - | `https://admin-rs.services.blockscout.com` | v1.1.0+ |
+| NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM | `string` | Link to form where authors can submit their dapps to the marketplace | Required | - | `https://airtable.com/shrqUAcjgGJ4jU88C` | v1.0.x+ |
+| NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM | `string` | Link to form where users can suggest ideas for the marketplace | - | - | `https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form` | v1.24.0+ |
+| NEXT_PUBLIC_NETWORK_RPC_URL | `string` | See in [Blockchain parameters](ENVS.md#blockchain-parameters) section | Required | - | `https://core.poa.network` | v1.0.x+ |
+| NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL | `string` | URL of configuration file (`.json` format only) which contains the list of categories to be displayed on the marketplace page in the specified order. If no URL is provided, then the list of categories will be compiled based on the `categories` fields from the marketplace (apps) configuration file | - | - | `https://example.com/marketplace_categories.json` | v1.23.0+ |
+| NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL | `string` | URL of configuration file (`.json` format only) which contains app security reports for displaying security scores on the Marketplace page | - | - | `https://example.com/marketplace_security_reports.json` | v1.28.0+ |
+| NEXT_PUBLIC_MARKETPLACE_FEATURED_APP | `string` | ID of the featured application to be displayed on the banner on the Marketplace page | - | - | `uniswap` | v1.29.0+ |
+| NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL | `string` | URL of the banner HTML content | - | - | `https://example.com/banner` | v1.29.0+ |
+| NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL | `string` | URL of the page the banner leads to | - | - | `https://example.com` | v1.29.0+ |
+| NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_API_KEY | `string` | Airtable API key | - | - | - | v1.33.0+ |
+| NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID | `string` | Airtable base ID with dapp ratings | - | - | - | v1.33.0+ |
+| NEXT_PUBLIC_MARKETPLACE_GRAPH_LINKS_URL | `string` | URL of the file (`.json` format only) which contains the list of The Graph links to be displayed on the Marketplace page | - | - | `https://example.com/graph_links.json` | v1.36.0+ |
+
+#### Marketplace app configuration properties
+
+| Property | Type | Description | Compulsoriness | Example value |
+| --- | --- | --- | --- | --- |
+| id | `string` | Used as slug for the app. Must be unique in the app list. | Required | `'app'` |
+| external | `boolean` | `true` means that the application opens in a new window, but not in an iframe. | - | `true` |
+| title | `string` | Displayed title of the app. | Required | `'The App'` |
+| logo | `string` | URL to logo file. Should be at least 288x288. | Required | `'https://foo.app/icon.png'` |
+| shortDescription | `string` | Displayed only in the app list. | Required | `'Awesome app'` |
+| categories | `Array` | Displayed category. | Required | `['Security', 'Tools']` |
+| author | `string` | Displayed author of the app | Required | `'Bob'` |
+| url | `string` | URL of the app which will be launched in the iframe. | Required | `'https://foo.app/launch'` |
+| description | `string` | Displayed only in the modal dialog with additional info about the app. | Required | `'The best app'` |
+| site | `string` | Displayed site link | - | `'https://blockscout.com'` |
+| twitter | `string` | Displayed twitter link | - | `'https://twitter.com/blockscoutcom'` |
+| telegram | `string` | Displayed telegram link | - | `'https://t.me/poa_network'` |
+| github | `string` | Displayed github link | - | `'https://github.com/blockscout'` |
+| internalWallet | `boolean` | `true` means that the application can automatically connect to the Blockscout wallet. | - | `true` |
+| priority | `number` | The higher the priority, the higher the app will appear in the list on the Marketplace page. | - | `7` |
+
+
+
+### Solidity to UML diagrams
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_VISUALIZE_API_HOST | `string` | Visualize API endpoint url | Required | - | `https://visualizer.services.blockscout.com` | v1.0.x+ |
+| NEXT_PUBLIC_VISUALIZE_API_BASE_PATH | `string` | Base path for Visualize API endpoint url | - | - | `/poa/core` | v1.29.0+ |
+
+
+
+### Blockchain statistics
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_STATS_API_HOST | `string` | Stats API endpoint url | Required | - | `https://stats.services.blockscout.com` | v1.0.x+ |
+| NEXT_PUBLIC_STATS_API_BASE_PATH | `string` | Base path for Stats API endpoint url | - | - | `/poa/core` | v1.29.0+ |
+
+
+
+### Web3 wallet integration (add token or network to the wallet)
+
+This feature is **enabled by default** with the `['metamask']` value. To switch it off pass `NEXT_PUBLIC_WEB3_WALLETS=none`.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_WEB3_WALLETS | `Array<'metamask' \| 'coinbase' \| 'token_pocket'>` | Array of Web3 wallets which will be used to add tokens or chain to. The first wallet which is enabled in user's browser will be shown. | - | `[ 'metamask' ]` | `[ 'coinbase' ]` | v1.10.0+ |
+| NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET | `boolean`| Set to `true` to hide icon "Add to your wallet" next to token addresses | - | - | `true` | v1.0.x+ |
+
+
+
+### Transaction interpretation
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER | `blockscout` \| `noves` \| `none` | Transaction interpretation provider that displays human readable transaction description | - | `none` | `blockscout` | v1.21.0+ |
+
+
+
+### External transactions
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_TX_EXTERNAL_TRANSACTIONS_CONFIG | `{ chain_name: string; chain_logo_url: string; explorer_url_template: string; }` | Configuration of the external transactions links that should be added to the transaction details. | - | - | `{ chain_name: 'ethereum', chain_logo_url: 'https://example.com/logo.png', explorer_url_template: 'https://explorer.com/tx/{hash}' }` | v1.38.0+ |
+
+
+
+### Verified tokens info
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_CONTRACT_INFO_API_HOST | `string` | Contract Info API endpoint url | Required | - | `https://contracts-info.services.blockscout.com` | v1.0.x+ |
+
+
+
+### Name service integration
+
+This feature allows resolving blockchain addresses using human-readable domain names.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_NAME_SERVICE_API_HOST | `string` | Name Service API endpoint url | Required | - | `https://bens.services.blockscout.com` | v1.22.0+ |
+
+
+
+### Metadata service integration
+
+This feature allows name tags and other public tags for addresses.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_METADATA_SERVICE_API_HOST | `string` | Metadata Service API endpoint url | Required | - | `https://metadata.services.blockscout.com` | v1.30.0+ |
+
+
+
+### Public tag submission
+
+This feature allows you to submit an application with a public address tag.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_METADATA_SERVICE_API_HOST | `string` | Metadata Service API endpoint url | Required | - | `https://metadata.services.blockscout.com` | v1.30.0+ |
+| NEXT_PUBLIC_ADMIN_SERVICE_API_HOST | `string` | Admin Service API endpoint url | Required | - | `https://admin-rs.services.blockscout.com` | v1.1.0+ |
+| NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY | `string` | See [below](ENVS.md#google-recaptcha) | true | - | `` | v1.0.x+ |
+
+
+
+### Data Availability
+
+This feature enables views related to blob transactions (EIP-4844), such as the Blob Txns tab on the Transactions page and the Blob details page.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED | `boolean` | Set to true to enable blob transactions views. | Required | - | `true` | v1.28.0+ |
+
+
+
+### Bridged tokens
+
+This feature allows users to view tokens that have been bridged from other EVM chains. Additional tab "Bridged" will be added to the tokens page and the link to original token will be displayed on the token page.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_BRIDGED_TOKENS_CHAINS | `Array` where `BridgedTokenChain` can have following [properties](#bridged-token-chain-configuration-properties) | Used for displaying filter by the chain from which token where bridged. Also, used for creating links to original tokens in other explorers. | Required | - | `[{'id':'1','title':'Ethereum','short_title':'ETH','base_url':'https://eth.blockscout.com/token'}]` | v1.14.0+ |
+| NEXT_PUBLIC_BRIDGED_TOKENS_BRIDGES | `Array` where `TokenBridge` can have following [properties](#token-bridge-configuration-properties) | Used for displaying text about bridges types on the tokens page. | Required | - | `[{'type':'omni','title':'OmniBridge','short_title':'OMNI'}]` | v1.14.0+ |
+
+#### Bridged token chain configuration properties
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value |
+| --- | --- | --- | --- | --- | --- |
+| id | `string` | Base chain id, see [https://chainlist.org](https://chainlist.org) for the reference | Required | - | `1` |
+| title | `string` | Displayed name of the chain | Required | - | `Ethereum` |
+| short_title | `string` | Used for displaying chain name in the list view as tag | Required | - | `ETH` |
+| base_url | `string` | Base url to original token in base chain explorer | Required | - | `https://eth.blockscout.com/token` |
+
+*Note* The url to original token will be constructed as `/`, e.g `https://eth.blockscout.com/token/`
+
+#### Token bridge configuration properties
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value |
+| --- | --- | --- | --- | --- | --- |
+| type | `string` | Bridge type; should be matched to `bridge_type` field in API response | Required | - | `omni` |
+| title | `string` | Bridge title | Required | - | `OmniBridge` |
+| short_title | `string` | Bridge short title for displaying in the tags | Required | - | `OMNI` |
+
+
+
+### Safe{Core} address tags
+
+For the smart contract addresses which are [Safe{Core} accounts](https://safe.global/) public tag "Multisig: Safe" will be displayed in the address page header alongside to Safe logo.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_SAFE_TX_SERVICE_URL | `string` | The Safe transaction service URL. See full list of supported networks [here](https://docs.safe.global/api-supported-networks). | - | - | `uniswap` | v1.26.0+ |
+
+
+
+### Address profile API
+
+This feature allows the integration of an external API to fetch user info for addresses or contracts. When configured, if the API returns a username, a public tag with a custom link will be displayed in the address page header.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_ADDRESS_USERNAME_TAG | `{api_url: string; tag_link_template: string; tag_icon: string; tag_bg_color: string; tag_text_color: string}` | Address profile API tag configuration properties. See [below](#user-profile-api-configuration-properties). | - | - | `uniswap` | v1.35.0+ |
+
+
+
+#### Address profile API configuration properties
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value |
+| --- | --- | --- | --- | --- | --- |
+| api_url_template | `string` | User profile API URL. Should be a template with `{address}` variable | Required | - | `https://example-api.com/{address}` |
+| tag_link_template | `string` | External link to the profile. Should be a template with `{username}` variable | - | - | `https://example.com/{address}` |
+| tag_icon | `string` | Public tag icon (.svg) url | - | - | `https://example.com/icon.svg` |
+| tag_bg_color | `string` | Public tag background color (escape "#" symbol if you use HEX color codes or use rgba-value instead) | - | - | `\#000000` |
+| tag_text_color | `string` | Public tag text color (escape "#" symbol if you use HEX color codes or use rgba-value instead) | - | - | `\#FFFFFF` |
+
+
+
+### Address XStar XHS score
+
+This feature allows the integration of an XStar API to fetch XHS score for addresses. When configured, if the API returns a score, a public tag with that score will be displayed in the address page header.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_XSTAR_SCORE_URL | `string` | XStar XHS score documentation URL for the address tag. Enables the XStar score feature. | - | - | `https://docs.xname.app/the-solution-adaptive-proof-of-humanity-on-blockchain/xhs-scoring-algorithm` | v1.36.0+ |
+
+
+
+### SUAVE chain
+
+For blockchains that implement SUAVE architecture additional fields will be shown on the transaction page ("Allowed peekers", "Kettle"). Users also will be able to see the list of all transactions for a particular Kettle in the separate view.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_IS_SUAVE_CHAIN | `boolean` | Set to true for blockchains with [SUAVE architecture](https://writings.flashbots.net/mevm-suave-centauri-and-beyond) | Required | - | `true` | v1.14.0+ |
+
+
+
+### Celo chain
+
+For blockchains that use the Celo platform. _Note_, that once the Celo mainnet becomes an L2 chain, these variables will be migrated to the Rollup configuration section.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_CELO_ENABLED | `boolean` | Indicates that it is a Celo-based chain. | - | - | `true` | v1.37.0+ |
+| NEXT_PUBLIC_CELO_L2_UPGRADE_BLOCK | `number` | Indicates the block number when the Celo-type chain transitioned to L2. This is used to display links to the Epoch block page from a regular block page. | - | - | `26369280` | v1.37.0+ |
+
+
+
+### MetaSuites extension
+
+Enables [MetaSuites browser extension](https://github.com/blocksecteam/metasuites) to integrate with the app views.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_METASUITES_ENABLED | `boolean` | Set to true to enable integration | Required | - | `true` | v1.26.0+ |
+
+
+
+### Validators list
+
+The feature enables the Validators page which provides detailed information about the validators of the PoS chains.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE | `'stability' \| 'blackfort' \| 'zilliqa'` | Chain type | Required | - | `'stability'` | v1.25.0+ |
+
+
+
+### Sentry error monitoring
+
+_Note_ This feature is **deprecated**. All ENV variables will be removed in the future releases.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_SENTRY_DSN | `string` | Client key for your Sentry.io app | Required | - | `` | v1.0.x+ |
+| SENTRY_CSP_REPORT_URI | `string` | URL for sending CSP-reports to your Sentry.io app | - | - | `` | v1.0.x+ |
+| NEXT_PUBLIC_SENTRY_ENABLE_TRACING | `boolean` | Enables tracing and performance monitoring in Sentry.io | - | `false` | `true` | v1.17.0+ |
+
+
+
+### Rollbar error monitoring
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN | `string` | Client token for your Rollbar project | Required | - | `` | v1.37.x+ |
+
+
+
+### OpenTelemetry
+
+OpenTelemetry SDK for Node.js app could be enabled by passing `OTEL_SDK_ENABLED=true` variable. Configure the OpenTelemetry Protocol Exporter by using the generic environment variables described in the [OT docs](https://opentelemetry.io/docs/specs/otel/protocol/exporter/#configuration-options). Note that this Next.js feature is currently experimental. The Docker image should be built with the `NEXT_OPEN_TELEMETRY_ENABLED=true` argument to enable it.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| OTEL_SDK_ENABLED | `boolean` | Run-time flag to enable the feature | Required | `false` | `true` | v1.18.0+ |
+
+
+
+### DeFi dropdown
+
+If the feature is enabled, a single button or a dropdown (if more than 1 item is provided) will be displayed at the top of the explorer page, which will take a user to the specified application in the marketplace or to an external site.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS | `[{ text: string; icon: string; dappId?: string, url?: string }]` | An array of dropdown items containing the button text, icon name and dappId in DAppscout or an external url | - | - | `[{'text':'Swap','icon':'swap','dappId':'uniswap'},{'text':'Payment link','icon':'payment_link','dappId':'peanut-protocol'}]` | v1.31.0+ |
+
+
+
+### Multichain balance button
+
+If the feature is enabled, a Multichain balance button will be displayed on the address page, which will take you to the portfolio application in the marketplace or to an external site.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG | `[{ name: string; url_template: string; dapp_id?: string; logo: string }]` | Multichain portfolio application config See [below](#multichain-button-configuration-properties) | - | - | `[{ name: 'zerion', url_template: 'https://app.zerion.io/{address}/overview', logo: 'https://example.com/icon.svg'}]` | v1.31.0+ |
+
+
+
+#### Multichain button configuration properties
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value |
+| --- | --- | --- | --- | --- | --- |
+| name | `string` | Multichain portfolio application name | Required | - | `zerion` |
+| url_template | `string` | Url template to the portfolio. Should be a template with `{address}` variable | Required | - | `https://app.zerion.io/{address}/overview` |
+| dapp_id | `string` | Set for open a Blockscout dapp page with the portfolio instead of opening external app page | - | - | `zerion` |
+| logo | `string` | Multichain portfolio application logo (.svg) url | - | - | `https://example.com/icon.svg` |
+
+
+
+### Get gas button
+
+If the feature is enabled, a Get gas button will be displayed in the top bar, which will take you to the gas refuel application in the marketplace or to an external site.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_GAS_REFUEL_PROVIDER_CONFIG | `{ name: string; url_template: string; dapp_id?: string; logo?: string }` | Get gas button config. See [below](#get-gas-button-configuration-properties) | - | - | `{ name: 'Need gas?', dapp_id: 'smol-refuel', url_template: 'https://smolrefuel.com/?outboundChain={chainId}', logo: 'https://example.com/icon.png' }` | v1.33.0+ |
+
+
+
+#### Get gas button configuration properties
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value |
+| --- | --- | --- | --- | --- | --- |
+| name | `string` | Text on the button | Required | - | `Need gas?` |
+| url_template | `string` | Url template, may contain `{chainId}` variable | Required | - | `https://smolrefuel.com/?outboundChain={chainId}` |
+| dapp_id | `string` | Set for open a Blockscout dapp page instead of opening external app page | - | - | `smol-refuel` |
+| logo | `string` | Gas refuel application logo url | - | - | `https://example.com/icon.png` |
+
+
+
+### Save on gas with GasHawk
+
+The feature enables a "Save with GasHawk" button next to the "Gas used" value on the address page.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_SAVE_ON_GAS_ENABLED | `boolean` | Set to "true" to enable the feature | - | - | `true` | v1.35.0+ |
+
+
+
+### Rewards service API
+
+This feature enables Blockscout Merits program. It requires that the [My account](ENVS.md#my-account) and [Blockchain interaction](ENVS.md#blockchain-interaction-writing-to-contract-etc) features are also enabled.
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_REWARDS_SERVICE_API_HOST | `string` | API URL | - | - | `https://example.com` | v1.36.0+ |
+
+
+
+### DEX pools
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_DEX_POOLS_ENABLED | `boolean` | Set to true to enable the feature | Required | - | `true` | v1.37.0+ |
+| NEXT_PUBLIC_CONTRACT_INFO_API_HOST | `string` | Contract Info API endpoint url | Required | - | `https://contracts-info.services.blockscout.com` | v1.0.x+ |
+
+
+
+### Badge claim link
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK | `string` | Provide to enable the easter egg badge feature | - | - | `https://example.com` | v1.37.0+ |
+
+
+
+## External services configuration
+
+### Google ReCaptcha
+
+For obtaining the variable values, please refer to the [reCAPTCHA documentation](https://developers.google.com/recaptcha). Please note that we currently support only **reCAPTCHA v2 in invisible mode**, read more [here](https://developers.google.com/recaptcha/docs/versions#recaptcha_v2_invisible_recaptcha_badge).
+
+| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
+| --- | --- | --- | --- | --- | --- | --- |
+| NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY | `string` | **DEPRECATED** Google reCAPTCHA v3 site key | - | - | `` | v1.36.x |
+| NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY | `string` | Google reCAPTCHA v2 site key | - | - | `` | v1.0.x+ |
\ No newline at end of file
diff --git a/explorer/frontend/docs/PULL_REQUEST_TEMPLATE.md b/explorer/frontend/docs/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 000000000..d4378762b
--- /dev/null
+++ b/explorer/frontend/docs/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,21 @@
+## Description and Related Issue(s)
+
+*[Provide a brief description of the changes or enhancements introduced by this pull request and explain motivation behind them. Cite any related issue(s) or bug(s) that it addresses using the [format](https://blog.github.com/2013-05-14-closing-issues-via-pull-requests/) `Fixes #123` or `Resolves #456`.]*
+
+### Proposed Changes
+*[Specify the changes or additions made in this pull request. Please mention if any changes were made to the ENV variables]*
+
+### Breaking or Incompatible Changes
+*[Describe any breaking or incompatible changes introduced by this pull request. Specify how users might need to modify their code or configurations to accommodate these changes.]*
+
+### Additional Information
+*[Include any additional information, context, or screenshots that may be helpful for reviewers.]*
+
+## Checklist for PR author
+- [ ] I have tested these changes locally.
+- [ ] I added tests to cover any new functionality, following this [guide](./CONTRIBUTING.md#writing--running-tests)
+- [ ] Whenever I fix a bug, I include a regression test to ensure that the bug does not reappear silently.
+- [ ] If I have added, changed, renamed, or removed an environment variable
+ - I updated the list of environment variables in the [documentation](ENVS.md)
+ - I made the necessary changes to the validator script according to the [guide](./CONTRIBUTING.md#adding-new-env-variable)
+ - I added "ENVs" label to this pull request
diff --git a/explorer/frontend/eslint.config.mjs b/explorer/frontend/eslint.config.mjs
new file mode 100644
index 000000000..534b16b64
--- /dev/null
+++ b/explorer/frontend/eslint.config.mjs
@@ -0,0 +1,452 @@
+import { includeIgnoreFile } from '@eslint/compat';
+import jsPlugin from '@eslint/js';
+import nextJsPlugin from '@next/eslint-plugin-next';
+import stylisticPlugin from '@stylistic/eslint-plugin';
+import reactQueryPlugin from '@tanstack/eslint-plugin-query';
+import importPlugin from 'eslint-plugin-import';
+import importHelpersPlugin from 'eslint-plugin-import-helpers';
+import jestPlugin from 'eslint-plugin-jest';
+import jsxA11yPlugin from 'eslint-plugin-jsx-a11y';
+import noCyrillicStringPlugin from 'eslint-plugin-no-cyrillic-string';
+import playwrightPlugin from 'eslint-plugin-playwright';
+import reactPlugin from 'eslint-plugin-react';
+import reactHooksPlugin from 'eslint-plugin-react-hooks';
+import * as regexpPlugin from 'eslint-plugin-regexp';
+import globals from 'globals';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+import tseslint from 'typescript-eslint';
+
+const RESTRICTED_MODULES = {
+ paths: [
+ { name: 'dayjs', message: 'Please use lib/date/dayjs.ts instead of directly importing dayjs' },
+ { name: '@chakra-ui/icons', message: 'Using @chakra-ui/icons is prohibited. Please use regular svg-icon instead (see examples in "icons/" folder)' },
+ { name: '@metamask/providers', message: 'Please lazy-load @metamask/providers or use useProvider hook instead' },
+ { name: '@metamask/post-message-stream', message: 'Please lazy-load @metamask/post-message-stream or use useProvider hook instead' },
+ { name: 'playwright/TestApp', message: 'Please use render() fixture from test() function of playwright/lib module' },
+ {
+ name: '@chakra-ui/react',
+ importNames: [
+ 'Menu', 'useToast', 'useDisclosure', 'useClipboard', 'Tooltip', 'Skeleton', 'IconButton', 'Button', 'ButtonGroup', 'Link', 'LinkBox', 'LinkOverlay',
+ 'Dialog', 'DialogRoot', 'DialogContent', 'DialogHeader', 'DialogCloseTrigger', 'DialogBody',
+ 'Tag', 'Switch', 'Image', 'Popover', 'PopoverTrigger', 'PopoverContent', 'PopoverBody', 'PopoverFooter',
+ 'DrawerRoot', 'DrawerBody', 'DrawerContent', 'DrawerOverlay', 'DrawerBackdrop', 'DrawerTrigger', 'Drawer',
+ 'Alert', 'AlertIcon', 'AlertTitle', 'AlertDescription',
+ 'Select', 'SelectRoot', 'SelectControl', 'SelectContent', 'SelectItem', 'SelectValueText',
+ 'Heading', 'Badge', 'Tabs', 'Show', 'Hide', 'Checkbox', 'CheckboxGroup',
+ 'Table', 'TableRoot', 'TableBody', 'TableHeader', 'TableRow', 'TableCell',
+ 'Menu', 'MenuRoot', 'MenuTrigger', 'MenuContent', 'MenuItem', 'MenuTriggerItem', 'MenuRadioItemGroup', 'MenuContextTrigger',
+ 'Rating', 'RatingGroup', 'Textarea',
+ ],
+ message: 'Please use corresponding component or hook from "toolkit" instead',
+ },
+ {
+ name: 'next/link',
+ importNames: [ 'default' ],
+ message: 'Please use toolkit/chakra/link component instead',
+ },
+ ],
+ patterns: [
+ 'icons/*',
+ ],
+};
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+const gitignorePath = path.resolve(__dirname, '.gitignore');
+
+/** @type {import('eslint').Linter.Config[]} */
+export default tseslint.config(
+ includeIgnoreFile(gitignorePath),
+
+ { files: [ '**/*.{js,mjs,cjs,ts,jsx,tsx}', '**/*.pw.tsx' ] },
+
+ { ignores: [
+ 'deploy/tools/',
+ 'public/',
+ '.git/',
+ 'next.config.js',
+ ] },
+
+ { languageOptions: { globals: { ...globals.browser, ...globals.node } } },
+
+ { settings: { react: { version: 'detect' } } },
+
+ jsPlugin.configs.recommended,
+
+ {
+ plugins: {
+ '@typescript-eslint': tseslint.plugin,
+ jest: jestPlugin,
+ },
+ languageOptions: {
+ parser: tseslint.parser,
+ parserOptions: {
+ projectService: true,
+ },
+ globals: jestPlugin.environments.globals.globals,
+ },
+ rules: {
+ '@typescript-eslint/array-type': [ 'error', {
+ 'default': 'generic',
+ readonly: 'generic',
+ } ],
+ '@typescript-eslint/consistent-type-imports': [ 'error' ],
+ '@typescript-eslint/naming-convention': [ 'error',
+ {
+ selector: 'default',
+ format: [ 'camelCase' ],
+ leadingUnderscore: 'allow',
+ trailingUnderscore: 'forbid',
+ },
+ {
+ selector: 'import',
+ leadingUnderscore: 'allow',
+ format: [ 'camelCase', 'PascalCase' ],
+ },
+ {
+ selector: 'class',
+ format: [ 'PascalCase' ],
+ },
+ {
+ selector: 'enum',
+ format: [ 'PascalCase', 'UPPER_CASE' ],
+ },
+ {
+ selector: 'enumMember',
+ format: [ 'camelCase', 'PascalCase', 'UPPER_CASE' ],
+ },
+ {
+ selector: 'function',
+ format: [ 'camelCase', 'PascalCase' ],
+ },
+ {
+ selector: 'interface',
+ format: [ 'PascalCase' ],
+ },
+ {
+ selector: 'method',
+ format: [ 'camelCase', 'snake_case', 'UPPER_CASE' ],
+ leadingUnderscore: 'allow',
+ },
+ {
+ selector: 'parameter',
+ format: [ 'camelCase', 'PascalCase' ],
+ leadingUnderscore: 'allow',
+ },
+ {
+ selector: 'property',
+ format: null,
+ },
+ {
+ selector: 'typeAlias',
+ format: [ 'PascalCase' ],
+ },
+ {
+ selector: 'typeLike',
+ format: [ 'PascalCase' ],
+ },
+ {
+ selector: 'typeParameter',
+ format: [ 'PascalCase', 'UPPER_CASE' ],
+ },
+ {
+ selector: 'variable',
+ format: [ 'camelCase', 'PascalCase', 'UPPER_CASE' ],
+ leadingUnderscore: 'allow',
+ },
+ ],
+ '@typescript-eslint/no-empty-function': [ 'off' ],
+ '@typescript-eslint/no-unused-vars': [ 'error', { caughtErrors: 'none', ignoreRestSiblings: true } ],
+ '@typescript-eslint/no-use-before-define': 'off',
+ '@typescript-eslint/no-useless-constructor': [ 'error' ],
+ '@typescript-eslint/no-explicit-any': [ 'error', { ignoreRestArgs: true } ],
+ '@typescript-eslint/no-unused-expressions': [ 'error', {
+ allowShortCircuit: true,
+ allowTernary: true,
+ } ],
+ },
+ },
+ {
+ // disable type-aware linting on JS files
+ files: [ '**/*.{js,mjs}' ],
+ ...tseslint.configs.disableTypeChecked,
+ },
+
+ {
+ plugins: {
+ react: reactPlugin,
+ },
+ rules: {
+ 'react/jsx-key': 'error',
+ 'react/jsx-no-bind': [ 'error', {
+ ignoreRefs: true,
+ } ],
+ 'react/jsx-curly-brace-presence': [ 'error', {
+ props: 'never',
+ children: 'never',
+ } ],
+ 'react/jsx-curly-spacing': 'off',
+ 'react/jsx-equals-spacing': [ 'error', 'never' ],
+ 'react/jsx-fragments': [ 'error', 'syntax' ],
+ 'react/jsx-no-duplicate-props': 'error',
+ 'react/jsx-no-target-blank': 'off',
+ 'react/jsx-no-useless-fragment': 'error',
+ 'react/jsx-wrap-multilines': [ 'error', {
+ declaration: 'parens-new-line',
+ assignment: 'parens-new-line',
+ 'return': 'parens-new-line',
+ arrow: 'parens-new-line',
+ condition: 'parens-new-line',
+ logical: 'parens-new-line',
+ prop: 'parens-new-line',
+ } ],
+ 'react/no-access-state-in-setstate': 'error',
+ 'react/no-deprecated': 'error',
+ 'react/no-direct-mutation-state': 'error',
+ 'react/no-find-dom-node': 'off',
+ 'react/no-redundant-should-component-update': 'error',
+ 'react/no-render-return-value': 'error',
+ 'react/no-string-refs': 'off',
+ 'react/no-unknown-property': 'error',
+ 'react/no-unused-state': 'error',
+ 'react/require-optimization': [ 'error' ],
+ 'react/void-dom-elements-no-children': 'error',
+ },
+ },
+
+ {
+ plugins: {
+ '@next/next': nextJsPlugin,
+ },
+ rules: {
+ ...nextJsPlugin.configs.recommended.rules,
+ ...nextJsPlugin.configs['core-web-vitals'].rules,
+ },
+ },
+
+ {
+ plugins: { '@tanstack/query': reactQueryPlugin },
+ },
+
+ {
+ ...playwrightPlugin.configs['flat/recommended'],
+ files: [ '**/*.pw.tsx' ],
+ rules: {
+ ...playwrightPlugin.configs['flat/recommended'].rules,
+ 'playwright/no-standalone-expect': 'off', // this rules does not work correctly with extended test functions
+ },
+ },
+
+ {
+ plugins: { 'react-hooks': reactHooksPlugin },
+ ignores: [ '**/*.pw.tsx', 'playwright/**' ],
+ rules: {
+ 'react-hooks/rules-of-hooks': 'error',
+ 'react-hooks/exhaustive-deps': 'error',
+ },
+ },
+
+ {
+ files: [ '**/*.test.{ts,js,jsx,tsx}' ],
+ plugins: { jest: jestPlugin },
+ languageOptions: {
+ globals: jestPlugin.environments.globals.globals,
+ },
+ },
+
+ regexpPlugin.configs['flat/recommended'],
+
+ {
+ plugins: {
+ 'import': importPlugin,
+ },
+ rules: {
+ 'import/no-duplicates': 'error',
+ },
+ },
+
+ {
+ plugins: {
+ 'import-helpers': importHelpersPlugin,
+ },
+ rules: {
+ 'import-helpers/order-imports': [
+ 'error',
+ {
+ newlinesBetween: 'always',
+ groups: [
+ 'module',
+ '/types/',
+ [ '/^nextjs/' ],
+ [
+ '/^configs/',
+ '/^data/',
+ '/^deploy/',
+ '/^icons/',
+ '/^jest/',
+ '/^lib/',
+ '/^mocks/',
+ '/^pages/',
+ '/^playwright/',
+ '/^stubs/',
+ '/^theme/',
+ '/^toolkit/',
+ '/^ui/',
+ ],
+ [ 'parent', 'sibling', 'index' ],
+ ],
+ alphabetize: { order: 'asc', ignoreCase: true },
+ },
+ ],
+ },
+ },
+
+ {
+ plugins: {
+ 'no-cyrillic-string': noCyrillicStringPlugin,
+ },
+ rules: {
+ 'no-cyrillic-string/no-cyrillic-string': 'error',
+ },
+ },
+
+ {
+ plugins: {
+ 'jsx-a11y': jsxA11yPlugin,
+ },
+ languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } },
+ },
+
+ {
+ plugins: {
+ '@stylistic': stylisticPlugin,
+ },
+ rules: {
+ // replacement for @typescript-eslint
+ '@stylistic/indent': [ 'error', 2 ],
+ '@stylistic/brace-style': [ 'error', '1tbs' ],
+ '@stylistic/member-delimiter-style': [ 'error' ],
+ '@stylistic/type-annotation-spacing': 'error',
+
+ // replacement for eslint
+ //'@stylistic/array-bracket-spacing': [ 'error', 'always' ],
+ '@stylistic/arrow-spacing': [ 'error', { before: true, after: true } ],
+ '@stylistic/comma-dangle': [ 'error', 'always-multiline' ],
+ '@stylistic/comma-spacing': [ 'error' ],
+ '@stylistic/comma-style': [ 'error', 'last' ],
+ '@stylistic/curly-newline': [ 'error', { multiline: true, minElements: 1 } ],
+ '@stylistic/eol-last': 'error',
+ '@stylistic/jsx-quotes': [ 'error', 'prefer-double' ],
+ '@stylistic/key-spacing': [ 'error', {
+ beforeColon: false,
+ afterColon: true,
+ } ],
+ '@stylistic/keyword-spacing': 'error',
+ '@stylistic/linebreak-style': [ 'error', 'unix' ],
+ '@stylistic/lines-around-comment': [ 'error', {
+ beforeBlockComment: true,
+ allowBlockStart: true,
+ } ],
+ '@stylistic/no-mixed-operators': [ 'error', {
+ groups: [
+ [ '&&', '||' ],
+ ],
+ } ],
+ '@stylistic/no-mixed-spaces-and-tabs': 'error',
+ '@stylistic/no-multiple-empty-lines': [ 'error', {
+ max: 1,
+ maxEOF: 0,
+ maxBOF: 0,
+ } ],
+ '@stylistic/no-multi-spaces': 'error',
+ '@stylistic/no-trailing-spaces': 'error',
+ '@stylistic/operator-linebreak': [ 'error', 'after' ],
+ '@stylistic/quote-props': [ 'error', 'as-needed', {
+ keywords: true,
+ numbers: true,
+ } ],
+ '@stylistic/quotes': [ 'error', 'single', {
+ allowTemplateLiterals: true,
+ } ],
+ '@stylistic/semi': [ 'error', 'always' ],
+ '@stylistic/space-before-function-paren': [ 'error', 'never' ],
+ '@stylistic/space-before-blocks': [ 'error', 'always' ],
+ '@stylistic/space-in-parens': [ 'error', 'never' ],
+ '@stylistic/space-infix-ops': 'error',
+ '@stylistic/space-unary-ops': 'off',
+ '@stylistic/template-curly-spacing': [ 'error', 'always' ],
+ '@stylistic/wrap-iife': [ 'error', 'inside' ],
+ },
+ },
+
+ {
+ rules: {
+ // disabled in favor of @typescript-eslint and @stylistic
+ 'no-use-before-define': 'off',
+ 'no-useless-constructor': 'off',
+ 'no-unused-vars': 'off',
+ 'no-empty': [ 'error', { allowEmptyCatch: true } ],
+ 'no-unused-expressions': 'off',
+
+ // this is checked by typescript compiler
+ 'no-redeclare': 'off',
+
+ // rules customizations
+ eqeqeq: [ 'error', 'allow-null' ],
+ 'id-match': [ 'error', '^[\\w$]+$' ],
+ 'max-len': [ 'error', 160, 4 ],
+ 'no-console': 'error',
+ 'no-implicit-coercion': [ 'error', {
+ number: true,
+ 'boolean': true,
+ string: true,
+ } ],
+ 'no-nested-ternary': 'error',
+ 'no-multi-str': 'error',
+ 'no-spaced-func': 'error',
+ 'no-with': 'error',
+ 'object-shorthand': 'off',
+ 'one-var': [ 'error', 'never' ],
+ 'prefer-const': 'error',
+
+ // restricted imports and properties
+ 'no-restricted-imports': [ 'error', RESTRICTED_MODULES ],
+ 'no-restricted-properties': [ 2, {
+ object: 'process',
+ property: 'env',
+ // FIXME: restrict the rule only NEXT_PUBLIC variables
+ message: 'Please use configs/app/index.ts to import any NEXT_PUBLIC environment variables. For other properties please disable this rule for a while.',
+ } ],
+ },
+ },
+ {
+ files: [
+ 'pages/**',
+ 'nextjs/**',
+ 'playwright/**',
+ 'deploy/scripts/**',
+ 'deploy/tools/**',
+ 'middleware.ts',
+ 'instrumentation*.ts',
+ '*.config.ts',
+ '*.config.js',
+ ],
+ rules: {
+ // for configs allow to consume env variables from process.env directly
+ 'no-restricted-properties': 'off',
+ },
+ },
+ {
+ files: [
+ 'toolkit/chakra/**',
+ 'toolkit/components/**',
+ 'toolkit/package/**',
+ ],
+ rules: {
+ // for toolkit components allow to import @chakra-ui/react directly
+ 'no-restricted-imports': 'off',
+ },
+ },
+);
diff --git a/explorer/frontend/global.d.ts b/explorer/frontend/global.d.ts
new file mode 100644
index 000000000..94cfa4677
--- /dev/null
+++ b/explorer/frontend/global.d.ts
@@ -0,0 +1,31 @@
+import type { WalletProvider } from 'types/web3';
+
+type CPreferences = {
+ zone: string;
+ width: string;
+ height: string;
+};
+
+declare global {
+ export interface Window {
+ ethereum?: WalletProvider | undefined;
+ coinzilla_display: Array;
+ ga?: {
+ getAll: () => Array<{ get: (prop: string) => string }>;
+ };
+ AdButler: {
+ ads: Array;
+ register: (...args: unknown) => void;
+ };
+ abkw: string;
+ __envs: Record;
+ }
+
+ namespace NodeJS {
+ interface ProcessEnv {
+ NODE_ENV: 'development' | 'production';
+ }
+ }
+}
+
+export {};
diff --git a/explorer/frontend/icons/ABI.svg b/explorer/frontend/icons/ABI.svg
new file mode 100644
index 000000000..0416e2e13
--- /dev/null
+++ b/explorer/frontend/icons/ABI.svg
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/ABI_slim.svg b/explorer/frontend/icons/ABI_slim.svg
new file mode 100644
index 000000000..89532207b
--- /dev/null
+++ b/explorer/frontend/icons/ABI_slim.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/API.svg b/explorer/frontend/icons/API.svg
new file mode 100644
index 000000000..2fae957e8
--- /dev/null
+++ b/explorer/frontend/icons/API.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/API_slim.svg b/explorer/frontend/icons/API_slim.svg
new file mode 100644
index 000000000..f4b36f08b
--- /dev/null
+++ b/explorer/frontend/icons/API_slim.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/ENS.svg b/explorer/frontend/icons/ENS.svg
new file mode 100644
index 000000000..9832944da
--- /dev/null
+++ b/explorer/frontend/icons/ENS.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/ENS_slim.svg b/explorer/frontend/icons/ENS_slim.svg
new file mode 100644
index 000000000..cd999b523
--- /dev/null
+++ b/explorer/frontend/icons/ENS_slim.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/MUD.svg b/explorer/frontend/icons/MUD.svg
new file mode 100644
index 000000000..8ab1229a7
--- /dev/null
+++ b/explorer/frontend/icons/MUD.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/MUD_menu.svg b/explorer/frontend/icons/MUD_menu.svg
new file mode 100644
index 000000000..c30c571c4
--- /dev/null
+++ b/explorer/frontend/icons/MUD_menu.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/RPC.svg b/explorer/frontend/icons/RPC.svg
new file mode 100644
index 000000000..7df2ba219
--- /dev/null
+++ b/explorer/frontend/icons/RPC.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/apps.svg b/explorer/frontend/icons/apps.svg
new file mode 100644
index 000000000..c0cdc1c4e
--- /dev/null
+++ b/explorer/frontend/icons/apps.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/apps_list.svg b/explorer/frontend/icons/apps_list.svg
new file mode 100644
index 000000000..62cb5020d
--- /dev/null
+++ b/explorer/frontend/icons/apps_list.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/apps_slim.svg b/explorer/frontend/icons/apps_slim.svg
new file mode 100644
index 000000000..59e2f2d81
--- /dev/null
+++ b/explorer/frontend/icons/apps_slim.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/arrows/down-right.svg b/explorer/frontend/icons/arrows/down-right.svg
new file mode 100644
index 000000000..e02aa2f9a
--- /dev/null
+++ b/explorer/frontend/icons/arrows/down-right.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/arrows/east-mini.svg b/explorer/frontend/icons/arrows/east-mini.svg
new file mode 100644
index 000000000..1a9d93e40
--- /dev/null
+++ b/explorer/frontend/icons/arrows/east-mini.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/arrows/east.svg b/explorer/frontend/icons/arrows/east.svg
new file mode 100644
index 000000000..c152a2f67
--- /dev/null
+++ b/explorer/frontend/icons/arrows/east.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/arrows/north-east.svg b/explorer/frontend/icons/arrows/north-east.svg
new file mode 100644
index 000000000..59aa6a4b2
--- /dev/null
+++ b/explorer/frontend/icons/arrows/north-east.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/arrows/south-east.svg b/explorer/frontend/icons/arrows/south-east.svg
new file mode 100644
index 000000000..16a7590f5
--- /dev/null
+++ b/explorer/frontend/icons/arrows/south-east.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/arrows/up-down.svg b/explorer/frontend/icons/arrows/up-down.svg
new file mode 100644
index 000000000..8f45bb257
--- /dev/null
+++ b/explorer/frontend/icons/arrows/up-down.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/arrows/up-head.svg b/explorer/frontend/icons/arrows/up-head.svg
new file mode 100644
index 000000000..375381a79
--- /dev/null
+++ b/explorer/frontend/icons/arrows/up-head.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/beta.svg b/explorer/frontend/icons/beta.svg
new file mode 100644
index 000000000..bba1309f3
--- /dev/null
+++ b/explorer/frontend/icons/beta.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/beta_xs.svg b/explorer/frontend/icons/beta_xs.svg
new file mode 100644
index 000000000..a6dc48ee4
--- /dev/null
+++ b/explorer/frontend/icons/beta_xs.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/blob.svg b/explorer/frontend/icons/blob.svg
new file mode 100644
index 000000000..9b40d72ec
--- /dev/null
+++ b/explorer/frontend/icons/blob.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/explorer/frontend/icons/blobs/image.svg b/explorer/frontend/icons/blobs/image.svg
new file mode 100644
index 000000000..be08dd269
--- /dev/null
+++ b/explorer/frontend/icons/blobs/image.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/blobs/raw.svg b/explorer/frontend/icons/blobs/raw.svg
new file mode 100644
index 000000000..8a97401ff
--- /dev/null
+++ b/explorer/frontend/icons/blobs/raw.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/blobs/text.svg b/explorer/frontend/icons/blobs/text.svg
new file mode 100644
index 000000000..08ec8801b
--- /dev/null
+++ b/explorer/frontend/icons/blobs/text.svg
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/block.svg b/explorer/frontend/icons/block.svg
new file mode 100644
index 000000000..85c88a6bd
--- /dev/null
+++ b/explorer/frontend/icons/block.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/block_countdown.svg b/explorer/frontend/icons/block_countdown.svg
new file mode 100644
index 000000000..0024e52ce
--- /dev/null
+++ b/explorer/frontend/icons/block_countdown.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/block_slim.svg b/explorer/frontend/icons/block_slim.svg
new file mode 100644
index 000000000..63302e1d8
--- /dev/null
+++ b/explorer/frontend/icons/block_slim.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/brands/blockscout.svg b/explorer/frontend/icons/brands/blockscout.svg
new file mode 100644
index 000000000..0e3279de0
--- /dev/null
+++ b/explorer/frontend/icons/brands/blockscout.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/brands/celenium.svg b/explorer/frontend/icons/brands/celenium.svg
new file mode 100644
index 000000000..8a5d645ac
--- /dev/null
+++ b/explorer/frontend/icons/brands/celenium.svg
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/brands/graph.svg b/explorer/frontend/icons/brands/graph.svg
new file mode 100644
index 000000000..bd3cc916d
--- /dev/null
+++ b/explorer/frontend/icons/brands/graph.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/brands/safe.svg b/explorer/frontend/icons/brands/safe.svg
new file mode 100644
index 000000000..836951383
--- /dev/null
+++ b/explorer/frontend/icons/brands/safe.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/brands/solidity_scan.svg b/explorer/frontend/icons/brands/solidity_scan.svg
new file mode 100644
index 000000000..ac5747c69
--- /dev/null
+++ b/explorer/frontend/icons/brands/solidity_scan.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/burger.svg b/explorer/frontend/icons/burger.svg
new file mode 100644
index 000000000..c6a84a911
--- /dev/null
+++ b/explorer/frontend/icons/burger.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/certified.svg b/explorer/frontend/icons/certified.svg
new file mode 100644
index 000000000..088a866f8
--- /dev/null
+++ b/explorer/frontend/icons/certified.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/check.svg b/explorer/frontend/icons/check.svg
new file mode 100644
index 000000000..563e6e5a9
--- /dev/null
+++ b/explorer/frontend/icons/check.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/checkered_flag.svg b/explorer/frontend/icons/checkered_flag.svg
new file mode 100644
index 000000000..918c29cea
--- /dev/null
+++ b/explorer/frontend/icons/checkered_flag.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/explorer/frontend/icons/clock-light.svg b/explorer/frontend/icons/clock-light.svg
new file mode 100644
index 000000000..110cd4b79
--- /dev/null
+++ b/explorer/frontend/icons/clock-light.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/clock.svg b/explorer/frontend/icons/clock.svg
new file mode 100644
index 000000000..14a8c9405
--- /dev/null
+++ b/explorer/frontend/icons/clock.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/close.svg b/explorer/frontend/icons/close.svg
new file mode 100644
index 000000000..0631c7c76
--- /dev/null
+++ b/explorer/frontend/icons/close.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/coins/bitcoin.svg b/explorer/frontend/icons/coins/bitcoin.svg
new file mode 100644
index 000000000..7f22b3139
--- /dev/null
+++ b/explorer/frontend/icons/coins/bitcoin.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/collection.svg b/explorer/frontend/icons/collection.svg
new file mode 100644
index 000000000..981040af5
--- /dev/null
+++ b/explorer/frontend/icons/collection.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/columns.svg b/explorer/frontend/icons/columns.svg
new file mode 100644
index 000000000..d4bfc9736
--- /dev/null
+++ b/explorer/frontend/icons/columns.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/contracts/proxy.svg b/explorer/frontend/icons/contracts/proxy.svg
new file mode 100644
index 000000000..1b75cb210
--- /dev/null
+++ b/explorer/frontend/icons/contracts/proxy.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/contracts/regular.svg b/explorer/frontend/icons/contracts/regular.svg
new file mode 100644
index 000000000..1bc8e0d3d
--- /dev/null
+++ b/explorer/frontend/icons/contracts/regular.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/contracts/regular_many.svg b/explorer/frontend/icons/contracts/regular_many.svg
new file mode 100644
index 000000000..1f0b62afd
--- /dev/null
+++ b/explorer/frontend/icons/contracts/regular_many.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/contracts/verified.svg b/explorer/frontend/icons/contracts/verified.svg
new file mode 100644
index 000000000..6dbb05843
--- /dev/null
+++ b/explorer/frontend/icons/contracts/verified.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/explorer/frontend/icons/contracts/verified_many.svg b/explorer/frontend/icons/contracts/verified_many.svg
new file mode 100644
index 000000000..2a004f596
--- /dev/null
+++ b/explorer/frontend/icons/contracts/verified_many.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/copy.svg b/explorer/frontend/icons/copy.svg
new file mode 100644
index 000000000..7b0b154c2
--- /dev/null
+++ b/explorer/frontend/icons/copy.svg
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/copy_check.svg b/explorer/frontend/icons/copy_check.svg
new file mode 100644
index 000000000..52a40f135
--- /dev/null
+++ b/explorer/frontend/icons/copy_check.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/cross.svg b/explorer/frontend/icons/cross.svg
new file mode 100644
index 000000000..c9bec2cef
--- /dev/null
+++ b/explorer/frontend/icons/cross.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/delete.svg b/explorer/frontend/icons/delete.svg
new file mode 100644
index 000000000..13b71cdff
--- /dev/null
+++ b/explorer/frontend/icons/delete.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/dex-tracker.svg b/explorer/frontend/icons/dex-tracker.svg
new file mode 100644
index 000000000..64deb3aed
--- /dev/null
+++ b/explorer/frontend/icons/dex-tracker.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/docs.svg b/explorer/frontend/icons/docs.svg
new file mode 100644
index 000000000..71a628d93
--- /dev/null
+++ b/explorer/frontend/icons/docs.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/donate.svg b/explorer/frontend/icons/donate.svg
new file mode 100644
index 000000000..9ed7def2b
--- /dev/null
+++ b/explorer/frontend/icons/donate.svg
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/dots.svg b/explorer/frontend/icons/dots.svg
new file mode 100644
index 000000000..1ea165f92
--- /dev/null
+++ b/explorer/frontend/icons/dots.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/explorer/frontend/icons/edit.svg b/explorer/frontend/icons/edit.svg
new file mode 100644
index 000000000..02a2737da
--- /dev/null
+++ b/explorer/frontend/icons/edit.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/email.svg b/explorer/frontend/icons/email.svg
new file mode 100644
index 000000000..4e184be0e
--- /dev/null
+++ b/explorer/frontend/icons/email.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/empty_search_result.svg b/explorer/frontend/icons/empty_search_result.svg
new file mode 100644
index 000000000..f4d62eff0
--- /dev/null
+++ b/explorer/frontend/icons/empty_search_result.svg
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/error-pages/403.svg b/explorer/frontend/icons/error-pages/403.svg
new file mode 100644
index 000000000..d4369a0a6
--- /dev/null
+++ b/explorer/frontend/icons/error-pages/403.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/error-pages/404.svg b/explorer/frontend/icons/error-pages/404.svg
new file mode 100644
index 000000000..296ff701c
--- /dev/null
+++ b/explorer/frontend/icons/error-pages/404.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/error-pages/422.svg b/explorer/frontend/icons/error-pages/422.svg
new file mode 100644
index 000000000..99225c643
--- /dev/null
+++ b/explorer/frontend/icons/error-pages/422.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/error-pages/429.svg b/explorer/frontend/icons/error-pages/429.svg
new file mode 100644
index 000000000..9ae110e19
--- /dev/null
+++ b/explorer/frontend/icons/error-pages/429.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/error-pages/500.svg b/explorer/frontend/icons/error-pages/500.svg
new file mode 100644
index 000000000..43cd887fd
--- /dev/null
+++ b/explorer/frontend/icons/error-pages/500.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/explorer.svg b/explorer/frontend/icons/explorer.svg
new file mode 100644
index 000000000..91a3e683f
--- /dev/null
+++ b/explorer/frontend/icons/explorer.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/files/csv.svg b/explorer/frontend/icons/files/csv.svg
new file mode 100644
index 000000000..119d58cdf
--- /dev/null
+++ b/explorer/frontend/icons/files/csv.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/files/image.svg b/explorer/frontend/icons/files/image.svg
new file mode 100644
index 000000000..9d2da4ee8
--- /dev/null
+++ b/explorer/frontend/icons/files/image.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/files/json.svg b/explorer/frontend/icons/files/json.svg
new file mode 100644
index 000000000..06c437efb
--- /dev/null
+++ b/explorer/frontend/icons/files/json.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/files/placeholder.svg b/explorer/frontend/icons/files/placeholder.svg
new file mode 100644
index 000000000..129e36a3b
--- /dev/null
+++ b/explorer/frontend/icons/files/placeholder.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/files/sol.svg b/explorer/frontend/icons/files/sol.svg
new file mode 100644
index 000000000..0efa5d0b3
--- /dev/null
+++ b/explorer/frontend/icons/files/sol.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/files/yul.svg b/explorer/frontend/icons/files/yul.svg
new file mode 100644
index 000000000..03b88fbb3
--- /dev/null
+++ b/explorer/frontend/icons/files/yul.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/filter.svg b/explorer/frontend/icons/filter.svg
new file mode 100644
index 000000000..c9c284e81
--- /dev/null
+++ b/explorer/frontend/icons/filter.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/flame.svg b/explorer/frontend/icons/flame.svg
new file mode 100644
index 000000000..ddc5f161e
--- /dev/null
+++ b/explorer/frontend/icons/flame.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/games.svg b/explorer/frontend/icons/games.svg
new file mode 100644
index 000000000..39c01ca56
--- /dev/null
+++ b/explorer/frontend/icons/games.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/gas.svg b/explorer/frontend/icons/gas.svg
new file mode 100644
index 000000000..4334fe93f
--- /dev/null
+++ b/explorer/frontend/icons/gas.svg
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/gas_xl.svg b/explorer/frontend/icons/gas_xl.svg
new file mode 100644
index 000000000..5a3913ac1
--- /dev/null
+++ b/explorer/frontend/icons/gas_xl.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/gear.svg b/explorer/frontend/icons/gear.svg
new file mode 100644
index 000000000..32ec463e1
--- /dev/null
+++ b/explorer/frontend/icons/gear.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/gear_slim.svg b/explorer/frontend/icons/gear_slim.svg
new file mode 100644
index 000000000..abc14e6a7
--- /dev/null
+++ b/explorer/frontend/icons/gear_slim.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/globe-b.svg b/explorer/frontend/icons/globe-b.svg
new file mode 100644
index 000000000..0b185e855
--- /dev/null
+++ b/explorer/frontend/icons/globe-b.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/globe.svg b/explorer/frontend/icons/globe.svg
new file mode 100644
index 000000000..e3cea4b63
--- /dev/null
+++ b/explorer/frontend/icons/globe.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/graphQL.svg b/explorer/frontend/icons/graphQL.svg
new file mode 100644
index 000000000..9332276ac
--- /dev/null
+++ b/explorer/frontend/icons/graphQL.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/heart_filled.svg b/explorer/frontend/icons/heart_filled.svg
new file mode 100644
index 000000000..64635b353
--- /dev/null
+++ b/explorer/frontend/icons/heart_filled.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/heart_outline.svg b/explorer/frontend/icons/heart_outline.svg
new file mode 100644
index 000000000..34c36398f
--- /dev/null
+++ b/explorer/frontend/icons/heart_outline.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/hourglass.svg b/explorer/frontend/icons/hourglass.svg
new file mode 100644
index 000000000..7ebd6d78b
--- /dev/null
+++ b/explorer/frontend/icons/hourglass.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/info.svg b/explorer/frontend/icons/info.svg
new file mode 100644
index 000000000..040100574
--- /dev/null
+++ b/explorer/frontend/icons/info.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/info_filled.svg b/explorer/frontend/icons/info_filled.svg
new file mode 100644
index 000000000..9616f0a2d
--- /dev/null
+++ b/explorer/frontend/icons/info_filled.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/integration/full.svg b/explorer/frontend/icons/integration/full.svg
new file mode 100644
index 000000000..0ac50a345
--- /dev/null
+++ b/explorer/frontend/icons/integration/full.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/integration/partial.svg b/explorer/frontend/icons/integration/partial.svg
new file mode 100644
index 000000000..2f7a76969
--- /dev/null
+++ b/explorer/frontend/icons/integration/partial.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/internal_txns.svg b/explorer/frontend/icons/internal_txns.svg
new file mode 100644
index 000000000..683cc0761
--- /dev/null
+++ b/explorer/frontend/icons/internal_txns.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/interop.svg b/explorer/frontend/icons/interop.svg
new file mode 100644
index 000000000..b5692777e
--- /dev/null
+++ b/explorer/frontend/icons/interop.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/key.svg b/explorer/frontend/icons/key.svg
new file mode 100644
index 000000000..ae0834f52
--- /dev/null
+++ b/explorer/frontend/icons/key.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/lightning.svg b/explorer/frontend/icons/lightning.svg
new file mode 100644
index 000000000..03fea73d7
--- /dev/null
+++ b/explorer/frontend/icons/lightning.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/lightning_navbar.svg b/explorer/frontend/icons/lightning_navbar.svg
new file mode 100644
index 000000000..9587a9c7a
--- /dev/null
+++ b/explorer/frontend/icons/lightning_navbar.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/link.svg b/explorer/frontend/icons/link.svg
new file mode 100644
index 000000000..5d072572a
--- /dev/null
+++ b/explorer/frontend/icons/link.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/link_external.svg b/explorer/frontend/icons/link_external.svg
new file mode 100644
index 000000000..dbddf710b
--- /dev/null
+++ b/explorer/frontend/icons/link_external.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/lock.svg b/explorer/frontend/icons/lock.svg
new file mode 100644
index 000000000..763d128cb
--- /dev/null
+++ b/explorer/frontend/icons/lock.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/explorer/frontend/icons/merits.svg b/explorer/frontend/icons/merits.svg
new file mode 100644
index 000000000..91b128a2b
--- /dev/null
+++ b/explorer/frontend/icons/merits.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/merits_colored.svg b/explorer/frontend/icons/merits_colored.svg
new file mode 100644
index 000000000..4006f7e43
--- /dev/null
+++ b/explorer/frontend/icons/merits_colored.svg
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/merits_slim.svg b/explorer/frontend/icons/merits_slim.svg
new file mode 100644
index 000000000..8a0623a16
--- /dev/null
+++ b/explorer/frontend/icons/merits_slim.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/merits_with_dot.svg b/explorer/frontend/icons/merits_with_dot.svg
new file mode 100644
index 000000000..e216115e4
--- /dev/null
+++ b/explorer/frontend/icons/merits_with_dot.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/merits_with_dot_slim.svg b/explorer/frontend/icons/merits_with_dot_slim.svg
new file mode 100644
index 000000000..4b5bf8a0a
--- /dev/null
+++ b/explorer/frontend/icons/merits_with_dot_slim.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/minus.svg b/explorer/frontend/icons/minus.svg
new file mode 100644
index 000000000..ba1cfe240
--- /dev/null
+++ b/explorer/frontend/icons/minus.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/monaco/cargo.svg b/explorer/frontend/icons/monaco/cargo.svg
new file mode 100644
index 000000000..ff0bf0e79
--- /dev/null
+++ b/explorer/frontend/icons/monaco/cargo.svg
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/monaco/file.svg b/explorer/frontend/icons/monaco/file.svg
new file mode 100644
index 000000000..38b4a10fc
--- /dev/null
+++ b/explorer/frontend/icons/monaco/file.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/monaco/folder-open.svg b/explorer/frontend/icons/monaco/folder-open.svg
new file mode 100644
index 000000000..02989af8d
--- /dev/null
+++ b/explorer/frontend/icons/monaco/folder-open.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/monaco/folder.svg b/explorer/frontend/icons/monaco/folder.svg
new file mode 100644
index 000000000..70e98efa4
--- /dev/null
+++ b/explorer/frontend/icons/monaco/folder.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/monaco/rust.svg b/explorer/frontend/icons/monaco/rust.svg
new file mode 100644
index 000000000..0966ea4b7
--- /dev/null
+++ b/explorer/frontend/icons/monaco/rust.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/monaco/solidity.svg b/explorer/frontend/icons/monaco/solidity.svg
new file mode 100644
index 000000000..f1c51a4c6
--- /dev/null
+++ b/explorer/frontend/icons/monaco/solidity.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/monaco/toml.svg b/explorer/frontend/icons/monaco/toml.svg
new file mode 100644
index 000000000..4217e7f6b
--- /dev/null
+++ b/explorer/frontend/icons/monaco/toml.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/monaco/vyper.svg b/explorer/frontend/icons/monaco/vyper.svg
new file mode 100644
index 000000000..cd7b34ad9
--- /dev/null
+++ b/explorer/frontend/icons/monaco/vyper.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/moon-with-star.svg b/explorer/frontend/icons/moon-with-star.svg
new file mode 100644
index 000000000..24c208587
--- /dev/null
+++ b/explorer/frontend/icons/moon-with-star.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/moon.svg b/explorer/frontend/icons/moon.svg
new file mode 100644
index 000000000..57c4ee656
--- /dev/null
+++ b/explorer/frontend/icons/moon.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/networks.svg b/explorer/frontend/icons/networks.svg
new file mode 100644
index 000000000..cc62a3579
--- /dev/null
+++ b/explorer/frontend/icons/networks.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/networks/icon-placeholder.svg b/explorer/frontend/icons/networks/icon-placeholder.svg
new file mode 100644
index 000000000..77414f1df
--- /dev/null
+++ b/explorer/frontend/icons/networks/icon-placeholder.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/networks/logo-placeholder.svg b/explorer/frontend/icons/networks/logo-placeholder.svg
new file mode 100644
index 000000000..6c7891fdb
--- /dev/null
+++ b/explorer/frontend/icons/networks/logo-placeholder.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/nft_shield.svg b/explorer/frontend/icons/nft_shield.svg
new file mode 100644
index 000000000..5f055f02e
--- /dev/null
+++ b/explorer/frontend/icons/nft_shield.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/open-link.svg b/explorer/frontend/icons/open-link.svg
new file mode 100644
index 000000000..d0fcc28ab
--- /dev/null
+++ b/explorer/frontend/icons/open-link.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/output_roots.svg b/explorer/frontend/icons/output_roots.svg
new file mode 100644
index 000000000..447e65743
--- /dev/null
+++ b/explorer/frontend/icons/output_roots.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/payment_link.svg b/explorer/frontend/icons/payment_link.svg
new file mode 100644
index 000000000..f97128fff
--- /dev/null
+++ b/explorer/frontend/icons/payment_link.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/plus.svg b/explorer/frontend/icons/plus.svg
new file mode 100644
index 000000000..b86a62118
--- /dev/null
+++ b/explorer/frontend/icons/plus.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/private_tags_slim.svg b/explorer/frontend/icons/private_tags_slim.svg
new file mode 100644
index 000000000..538c47d05
--- /dev/null
+++ b/explorer/frontend/icons/private_tags_slim.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/explorer/frontend/icons/privattags.svg b/explorer/frontend/icons/privattags.svg
new file mode 100644
index 000000000..7e0cacaa0
--- /dev/null
+++ b/explorer/frontend/icons/privattags.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/explorer/frontend/icons/profile.svg b/explorer/frontend/icons/profile.svg
new file mode 100644
index 000000000..177eea965
--- /dev/null
+++ b/explorer/frontend/icons/profile.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/publictags.svg b/explorer/frontend/icons/publictags.svg
new file mode 100644
index 000000000..4c55542fc
--- /dev/null
+++ b/explorer/frontend/icons/publictags.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/publictags_slim.svg b/explorer/frontend/icons/publictags_slim.svg
new file mode 100644
index 000000000..4de98a2d1
--- /dev/null
+++ b/explorer/frontend/icons/publictags_slim.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/qr_code.svg b/explorer/frontend/icons/qr_code.svg
new file mode 100644
index 000000000..f31b981da
--- /dev/null
+++ b/explorer/frontend/icons/qr_code.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/refresh.svg b/explorer/frontend/icons/refresh.svg
new file mode 100644
index 000000000..fef0346a5
--- /dev/null
+++ b/explorer/frontend/icons/refresh.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/repeat.svg b/explorer/frontend/icons/repeat.svg
new file mode 100644
index 000000000..dcd2c7a37
--- /dev/null
+++ b/explorer/frontend/icons/repeat.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/restAPI.svg b/explorer/frontend/icons/restAPI.svg
new file mode 100644
index 000000000..8924b2e2b
--- /dev/null
+++ b/explorer/frontend/icons/restAPI.svg
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/rocket.svg b/explorer/frontend/icons/rocket.svg
new file mode 100644
index 000000000..46523e1b0
--- /dev/null
+++ b/explorer/frontend/icons/rocket.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/rocket_xl.svg b/explorer/frontend/icons/rocket_xl.svg
new file mode 100644
index 000000000..8b3f4ccdb
--- /dev/null
+++ b/explorer/frontend/icons/rocket_xl.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/scope.svg b/explorer/frontend/icons/scope.svg
new file mode 100644
index 000000000..6337932af
--- /dev/null
+++ b/explorer/frontend/icons/scope.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/score/score-not-ok.svg b/explorer/frontend/icons/score/score-not-ok.svg
new file mode 100644
index 000000000..9b4533f6a
--- /dev/null
+++ b/explorer/frontend/icons/score/score-not-ok.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/score/score-ok.svg b/explorer/frontend/icons/score/score-ok.svg
new file mode 100644
index 000000000..dbe11836f
--- /dev/null
+++ b/explorer/frontend/icons/score/score-ok.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/search.svg b/explorer/frontend/icons/search.svg
new file mode 100644
index 000000000..c1849adc0
--- /dev/null
+++ b/explorer/frontend/icons/search.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/share.svg b/explorer/frontend/icons/share.svg
new file mode 100644
index 000000000..f1124e47d
--- /dev/null
+++ b/explorer/frontend/icons/share.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/sign_out.svg b/explorer/frontend/icons/sign_out.svg
new file mode 100644
index 000000000..d5b68ecda
--- /dev/null
+++ b/explorer/frontend/icons/sign_out.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/social/coingecko.svg b/explorer/frontend/icons/social/coingecko.svg
new file mode 100644
index 000000000..baf56eef3
--- /dev/null
+++ b/explorer/frontend/icons/social/coingecko.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/social/coinmarketcap.svg b/explorer/frontend/icons/social/coinmarketcap.svg
new file mode 100644
index 000000000..0341e03c4
--- /dev/null
+++ b/explorer/frontend/icons/social/coinmarketcap.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/social/defi_llama.svg b/explorer/frontend/icons/social/defi_llama.svg
new file mode 100644
index 000000000..f7d2cc51a
--- /dev/null
+++ b/explorer/frontend/icons/social/defi_llama.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/social/discord.svg b/explorer/frontend/icons/social/discord.svg
new file mode 100644
index 000000000..133a54e97
--- /dev/null
+++ b/explorer/frontend/icons/social/discord.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/social/discord_filled.svg b/explorer/frontend/icons/social/discord_filled.svg
new file mode 100644
index 000000000..691efc8a4
--- /dev/null
+++ b/explorer/frontend/icons/social/discord_filled.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/social/facebook_filled.svg b/explorer/frontend/icons/social/facebook_filled.svg
new file mode 100644
index 000000000..12afda197
--- /dev/null
+++ b/explorer/frontend/icons/social/facebook_filled.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/social/git.svg b/explorer/frontend/icons/social/git.svg
new file mode 100644
index 000000000..caf39a4c9
--- /dev/null
+++ b/explorer/frontend/icons/social/git.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/social/github_filled.svg b/explorer/frontend/icons/social/github_filled.svg
new file mode 100644
index 000000000..e134fcaf9
--- /dev/null
+++ b/explorer/frontend/icons/social/github_filled.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/social/linkedin_filled.svg b/explorer/frontend/icons/social/linkedin_filled.svg
new file mode 100644
index 000000000..6fcd9bedf
--- /dev/null
+++ b/explorer/frontend/icons/social/linkedin_filled.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/social/medium_filled.svg b/explorer/frontend/icons/social/medium_filled.svg
new file mode 100644
index 000000000..60f2d6303
--- /dev/null
+++ b/explorer/frontend/icons/social/medium_filled.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/social/opensea_filled.svg b/explorer/frontend/icons/social/opensea_filled.svg
new file mode 100644
index 000000000..a6c8798cc
--- /dev/null
+++ b/explorer/frontend/icons/social/opensea_filled.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/social/reddit_filled.svg b/explorer/frontend/icons/social/reddit_filled.svg
new file mode 100644
index 000000000..a57d9f797
--- /dev/null
+++ b/explorer/frontend/icons/social/reddit_filled.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/social/slack_filled.svg b/explorer/frontend/icons/social/slack_filled.svg
new file mode 100644
index 000000000..177f97122
--- /dev/null
+++ b/explorer/frontend/icons/social/slack_filled.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/social/stats.svg b/explorer/frontend/icons/social/stats.svg
new file mode 100644
index 000000000..cfc239f88
--- /dev/null
+++ b/explorer/frontend/icons/social/stats.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/social/telega.svg b/explorer/frontend/icons/social/telega.svg
new file mode 100644
index 000000000..432bc5c76
--- /dev/null
+++ b/explorer/frontend/icons/social/telega.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/social/telegram_filled.svg b/explorer/frontend/icons/social/telegram_filled.svg
new file mode 100644
index 000000000..87a2ebf52
--- /dev/null
+++ b/explorer/frontend/icons/social/telegram_filled.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/social/twitter.svg b/explorer/frontend/icons/social/twitter.svg
new file mode 100644
index 000000000..21e9812ff
--- /dev/null
+++ b/explorer/frontend/icons/social/twitter.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/social/twitter_filled.svg b/explorer/frontend/icons/social/twitter_filled.svg
new file mode 100644
index 000000000..0d73b850a
--- /dev/null
+++ b/explorer/frontend/icons/social/twitter_filled.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/star_filled.svg b/explorer/frontend/icons/star_filled.svg
new file mode 100644
index 000000000..7b6312c87
--- /dev/null
+++ b/explorer/frontend/icons/star_filled.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/star_outline.svg b/explorer/frontend/icons/star_outline.svg
new file mode 100644
index 000000000..05286fa1d
--- /dev/null
+++ b/explorer/frontend/icons/star_outline.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/stats.svg b/explorer/frontend/icons/stats.svg
new file mode 100644
index 000000000..127477d18
--- /dev/null
+++ b/explorer/frontend/icons/stats.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/status/error.svg b/explorer/frontend/icons/status/error.svg
new file mode 100644
index 000000000..3f7dff92c
--- /dev/null
+++ b/explorer/frontend/icons/status/error.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/status/pending.svg b/explorer/frontend/icons/status/pending.svg
new file mode 100644
index 000000000..f9e5a88d5
--- /dev/null
+++ b/explorer/frontend/icons/status/pending.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/explorer/frontend/icons/status/success.svg b/explorer/frontend/icons/status/success.svg
new file mode 100644
index 000000000..ce76c56a4
--- /dev/null
+++ b/explorer/frontend/icons/status/success.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/status/warning.svg b/explorer/frontend/icons/status/warning.svg
new file mode 100644
index 000000000..c177aea5a
--- /dev/null
+++ b/explorer/frontend/icons/status/warning.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/sun.svg b/explorer/frontend/icons/sun.svg
new file mode 100644
index 000000000..f90bf90ea
--- /dev/null
+++ b/explorer/frontend/icons/sun.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/swap.svg b/explorer/frontend/icons/swap.svg
new file mode 100644
index 000000000..c1566be5f
--- /dev/null
+++ b/explorer/frontend/icons/swap.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/testnet.svg b/explorer/frontend/icons/testnet.svg
new file mode 100644
index 000000000..ff01ccf7a
--- /dev/null
+++ b/explorer/frontend/icons/testnet.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/token-placeholder.svg b/explorer/frontend/icons/token-placeholder.svg
new file mode 100644
index 000000000..92307c47e
--- /dev/null
+++ b/explorer/frontend/icons/token-placeholder.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/token-transfers.svg b/explorer/frontend/icons/token-transfers.svg
new file mode 100644
index 000000000..f3bef44d8
--- /dev/null
+++ b/explorer/frontend/icons/token-transfers.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/token.svg b/explorer/frontend/icons/token.svg
new file mode 100644
index 000000000..933d69406
--- /dev/null
+++ b/explorer/frontend/icons/token.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/tokens.svg b/explorer/frontend/icons/tokens.svg
new file mode 100644
index 000000000..40c10466d
--- /dev/null
+++ b/explorer/frontend/icons/tokens.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/tokens/xdai.svg b/explorer/frontend/icons/tokens/xdai.svg
new file mode 100644
index 000000000..6a719eb2b
--- /dev/null
+++ b/explorer/frontend/icons/tokens/xdai.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/top-accounts.svg b/explorer/frontend/icons/top-accounts.svg
new file mode 100644
index 000000000..272f4742a
--- /dev/null
+++ b/explorer/frontend/icons/top-accounts.svg
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/transactions.svg b/explorer/frontend/icons/transactions.svg
new file mode 100644
index 000000000..3cefc2141
--- /dev/null
+++ b/explorer/frontend/icons/transactions.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/transactions_slim.svg b/explorer/frontend/icons/transactions_slim.svg
new file mode 100644
index 000000000..412f46aa3
--- /dev/null
+++ b/explorer/frontend/icons/transactions_slim.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/txn_batches.svg b/explorer/frontend/icons/txn_batches.svg
new file mode 100644
index 000000000..00dd273c2
--- /dev/null
+++ b/explorer/frontend/icons/txn_batches.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/txn_batches_slim.svg b/explorer/frontend/icons/txn_batches_slim.svg
new file mode 100644
index 000000000..b10a43073
--- /dev/null
+++ b/explorer/frontend/icons/txn_batches_slim.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/uniswap.svg b/explorer/frontend/icons/uniswap.svg
new file mode 100644
index 000000000..7abbc79f0
--- /dev/null
+++ b/explorer/frontend/icons/uniswap.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/user_op.svg b/explorer/frontend/icons/user_op.svg
new file mode 100644
index 000000000..02bc70140
--- /dev/null
+++ b/explorer/frontend/icons/user_op.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/user_op_slim.svg b/explorer/frontend/icons/user_op_slim.svg
new file mode 100644
index 000000000..d8c64b52b
--- /dev/null
+++ b/explorer/frontend/icons/user_op_slim.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/validator.svg b/explorer/frontend/icons/validator.svg
new file mode 100644
index 000000000..e77bb0ba5
--- /dev/null
+++ b/explorer/frontend/icons/validator.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/verification-steps/finalized.svg b/explorer/frontend/icons/verification-steps/finalized.svg
new file mode 100644
index 000000000..fbae66d63
--- /dev/null
+++ b/explorer/frontend/icons/verification-steps/finalized.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/verification-steps/unfinalized.svg b/explorer/frontend/icons/verification-steps/unfinalized.svg
new file mode 100644
index 000000000..49fdbc7dd
--- /dev/null
+++ b/explorer/frontend/icons/verification-steps/unfinalized.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/icons/verified.svg b/explorer/frontend/icons/verified.svg
new file mode 100644
index 000000000..8d6d5eecd
--- /dev/null
+++ b/explorer/frontend/icons/verified.svg
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/verified_slim.svg b/explorer/frontend/icons/verified_slim.svg
new file mode 100644
index 000000000..a13930aab
--- /dev/null
+++ b/explorer/frontend/icons/verified_slim.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/wallet.svg b/explorer/frontend/icons/wallet.svg
new file mode 100644
index 000000000..f1765c246
--- /dev/null
+++ b/explorer/frontend/icons/wallet.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/explorer/frontend/icons/wallets/coinbase.svg b/explorer/frontend/icons/wallets/coinbase.svg
new file mode 100644
index 000000000..9a75b44e6
--- /dev/null
+++ b/explorer/frontend/icons/wallets/coinbase.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/wallets/metamask.svg b/explorer/frontend/icons/wallets/metamask.svg
new file mode 100644
index 000000000..220fbc130
--- /dev/null
+++ b/explorer/frontend/icons/wallets/metamask.svg
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/wallets/token-pocket.svg b/explorer/frontend/icons/wallets/token-pocket.svg
new file mode 100644
index 000000000..fefaa9f26
--- /dev/null
+++ b/explorer/frontend/icons/wallets/token-pocket.svg
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/explorer/frontend/icons/watchlist.svg b/explorer/frontend/icons/watchlist.svg
new file mode 100644
index 000000000..6570c0406
--- /dev/null
+++ b/explorer/frontend/icons/watchlist.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/explorer/frontend/instrumentation.node.ts b/explorer/frontend/instrumentation.node.ts
new file mode 100644
index 000000000..a42232f4b
--- /dev/null
+++ b/explorer/frontend/instrumentation.node.ts
@@ -0,0 +1,71 @@
+/* eslint-disable no-console */
+import { diag, DiagConsoleLogger, DiagLogLevel } from '@opentelemetry/api';
+import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
+import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-proto';
+import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
+import { Resource } from '@opentelemetry/resources';
+import {
+ PeriodicExportingMetricReader,
+ ConsoleMetricExporter,
+} from '@opentelemetry/sdk-metrics';
+import { NodeSDK } from '@opentelemetry/sdk-node';
+import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node';
+import { SEMRESATTRS_SERVICE_NAME, SEMRESATTRS_SERVICE_VERSION, SEMRESATTRS_SERVICE_INSTANCE_ID } from '@opentelemetry/semantic-conventions';
+
+diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.INFO);
+
+const traceExporter = new OTLPTraceExporter();
+
+const sdk = new NodeSDK({
+ resource: new Resource({
+ [SEMRESATTRS_SERVICE_NAME]: 'blockscout_frontend',
+ [SEMRESATTRS_SERVICE_VERSION]: process.env.NEXT_PUBLIC_GIT_TAG || process.env.NEXT_PUBLIC_GIT_COMMIT_SHA || 'unknown_version',
+ [SEMRESATTRS_SERVICE_INSTANCE_ID]:
+ process.env.NEXT_PUBLIC_APP_INSTANCE ||
+ process.env.NEXT_PUBLIC_APP_HOST?.replace('.blockscout.com', '').replaceAll('-', '_') ||
+ 'unknown_app',
+ }),
+ spanProcessor: new SimpleSpanProcessor(traceExporter),
+ traceExporter,
+ metricReader: new PeriodicExportingMetricReader({
+ exporter:
+ process.env.NODE_ENV === 'production' ?
+ new OTLPMetricExporter() :
+ new ConsoleMetricExporter(),
+ }),
+ instrumentations: [
+ getNodeAutoInstrumentations({
+ '@opentelemetry/instrumentation-http': {
+ ignoreIncomingRequestHook: (request) => {
+ try {
+ if (!request.url) {
+ return false;
+ }
+ const url = new URL(request.url, `http://${ request.headers.host }`);
+ if (
+ url.pathname.startsWith('/_next/static/') ||
+ url.pathname.startsWith('/_next/data/') ||
+ url.pathname.startsWith('/assets/') ||
+ url.pathname.startsWith('/static/')
+ ) {
+ return true;
+ }
+ } catch (error) {}
+ return false;
+ },
+ },
+ }),
+ ],
+});
+
+if (process.env.OTEL_SDK_ENABLED) {
+ sdk.start();
+
+ process.on('SIGTERM', () => {
+ sdk
+ .shutdown()
+ .then(() => console.log('Tracing terminated'))
+ .catch((error) => console.log('Error terminating tracing', error))
+ .finally(() => process.exit(0));
+ });
+}
diff --git a/explorer/frontend/instrumentation.ts b/explorer/frontend/instrumentation.ts
new file mode 100644
index 000000000..dc366667c
--- /dev/null
+++ b/explorer/frontend/instrumentation.ts
@@ -0,0 +1,5 @@
+export async function register() {
+ if (process.env.NEXT_RUNTIME === 'nodejs' && process.env.NEXT_OPEN_TELEMETRY_ENABLED === 'true') {
+ await import('./instrumentation.node');
+ }
+}
diff --git a/explorer/frontend/jest.config.ts b/explorer/frontend/jest.config.ts
new file mode 100644
index 000000000..d718d56a7
--- /dev/null
+++ b/explorer/frontend/jest.config.ts
@@ -0,0 +1,40 @@
+import type { JestConfigWithTsJest } from 'ts-jest';
+
+/*
+ * For a detailed explanation regarding each configuration property and type check, visit:
+ * https://jestjs.io/docs/configuration
+ */
+
+const config: JestConfigWithTsJest = {
+ clearMocks: true,
+ coverageProvider: 'v8',
+ globalSetup: '/jest/global-setup.ts',
+ moduleDirectories: [
+ 'node_modules',
+ __dirname,
+ ],
+ moduleNameMapper: {
+ '^jest/(.*)': '/jest/$1',
+ },
+ modulePathIgnorePatterns: [
+ 'node_modules_linux',
+ ],
+ preset: 'ts-jest',
+ reporters: [ 'default', 'github-actions' ],
+ setupFiles: [
+ '/jest/setup.ts',
+ ],
+ testEnvironment: 'jsdom',
+ transform: {
+ // '^.+\\.[tj]sx?$' to process js/ts with `ts-jest`
+ // '^.+\\.m?[tj]sx?$' to process js/ts/mjs/mts with `ts-jest`
+ '^.+\\.tsx?$': [
+ 'ts-jest',
+ {
+ tsconfig: 'tsconfig.jest.json',
+ },
+ ],
+ },
+};
+
+export default config;
diff --git a/explorer/frontend/jest/global-setup.ts b/explorer/frontend/jest/global-setup.ts
new file mode 100644
index 000000000..1d17469be
--- /dev/null
+++ b/explorer/frontend/jest/global-setup.ts
@@ -0,0 +1,5 @@
+import dotenv from 'dotenv';
+
+export default async function globalSetup() {
+ dotenv.config({ path: './configs/envs/.env.jest' });
+}
diff --git a/explorer/frontend/jest/lib.tsx b/explorer/frontend/jest/lib.tsx
new file mode 100644
index 000000000..f6119698c
--- /dev/null
+++ b/explorer/frontend/jest/lib.tsx
@@ -0,0 +1,57 @@
+import { GrowthBookProvider } from '@growthbook/growthbook-react';
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
+import type { RenderOptions } from '@testing-library/react';
+import { render } from '@testing-library/react';
+import React from 'react';
+
+import { AppContextProvider } from 'lib/contexts/app';
+import { ScrollDirectionProvider } from 'lib/contexts/scrollDirection';
+import { SocketProvider } from 'lib/socket/context';
+import { Provider as ChakraProvider } from 'toolkit/chakra/provider';
+
+import 'lib/setLocale';
+
+const PAGE_PROPS = {
+ cookies: '',
+ referrer: '',
+ query: {},
+ adBannerProvider: null,
+ apiData: null,
+ uuid: '123',
+};
+
+const TestApp = ({ children }: { children: React.ReactNode }) => {
+ const [ queryClient ] = React.useState(() => new QueryClient({
+ defaultOptions: {
+ queries: {
+ refetchOnWindowFocus: false,
+ retry: 0,
+ },
+ },
+ }));
+
+ return (
+
+
+
+
+
+
+ { children }
+
+
+
+
+
+
+ );
+};
+
+const customRender = (
+ ui: React.ReactElement,
+ options?: Omit,
+) => render(ui, { wrapper: TestApp, ...options });
+
+export * from '@testing-library/react';
+export { customRender as render };
+export { TestApp as wrapper };
diff --git a/explorer/frontend/jest/mocks/next-router.ts b/explorer/frontend/jest/mocks/next-router.ts
new file mode 100644
index 000000000..4213a7ab9
--- /dev/null
+++ b/explorer/frontend/jest/mocks/next-router.ts
@@ -0,0 +1,17 @@
+import type { NextRouter } from 'next/router';
+
+export const router = {
+ query: {},
+ push: jest.fn(() => Promise.resolve()),
+};
+
+export const useRouter = jest.fn>>(() => (router));
+
+export const mockUseRouter = (params?: Partial) => {
+ return {
+ useRouter: jest.fn(() => ({
+ ...router,
+ ...params,
+ })),
+ };
+};
diff --git a/explorer/frontend/jest/setup.ts b/explorer/frontend/jest/setup.ts
new file mode 100644
index 000000000..d64cff2d4
--- /dev/null
+++ b/explorer/frontend/jest/setup.ts
@@ -0,0 +1,55 @@
+import dotenv from 'dotenv';
+import { TextEncoder, TextDecoder } from 'util';
+
+import fetchMock from 'jest-fetch-mock';
+
+fetchMock.enableMocks();
+
+const envs = dotenv.config({ path: './configs/envs/.env.jest' });
+
+Object.assign(global, { TextDecoder, TextEncoder });
+
+Object.defineProperty(window, 'matchMedia', {
+ writable: true,
+ value: jest.fn().mockImplementation(query => ({
+ matches: false,
+ media: query,
+ onchange: null,
+ addListener: jest.fn(),
+ removeListener: jest.fn(),
+ addEventListener: jest.fn(),
+ removeEventListener: jest.fn(),
+ dispatchEvent: jest.fn(),
+ })),
+});
+
+Object.defineProperty(window, '__envs', {
+ writable: true,
+ value: envs.parsed || {},
+});
+
+// eslint-disable-next-line no-console
+const consoleError = console.error;
+
+global.console = {
+ ...console,
+ error: (...args) => {
+ // silence some irrelevant errors
+ if (args.some((arg) => typeof arg === 'string' && arg.includes('Using kebab-case for css properties'))) {
+ return;
+ }
+ consoleError(...args);
+ },
+};
+
+// Polyfill for structuredClone
+if (typeof structuredClone === 'undefined') {
+ global.structuredClone = (obj: T): T => {
+ try {
+ return JSON.parse(JSON.stringify(obj)) as T;
+ } catch (error) {
+ // Fallback for circular references and other special cases
+ return obj;
+ }
+ };
+}
diff --git a/explorer/frontend/jest/utils/flushPromises.ts b/explorer/frontend/jest/utils/flushPromises.ts
new file mode 100644
index 000000000..2910c7deb
--- /dev/null
+++ b/explorer/frontend/jest/utils/flushPromises.ts
@@ -0,0 +1,7 @@
+const scheduler = typeof setImmediate === 'function' ? setImmediate : setTimeout;
+
+export default function flushPromises() {
+ return new Promise(function(resolve) {
+ scheduler(resolve);
+ });
+}
diff --git a/explorer/frontend/lib/address/bech32.ts b/explorer/frontend/lib/address/bech32.ts
new file mode 100644
index 000000000..85fcfda3e
--- /dev/null
+++ b/explorer/frontend/lib/address/bech32.ts
@@ -0,0 +1,49 @@
+import { bech32 } from '@scure/base';
+
+import config from 'configs/app';
+import bytesToHex from 'lib/bytesToHex';
+import hexToBytes from 'lib/hexToBytes';
+
+export const DATA_PART_REGEXP = /^[\da-z]{38}$/;
+export const BECH_32_SEPARATOR = '1'; // https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#bech32
+
+export function toBech32Address(hash: string) {
+ if (config.UI.views.address.hashFormat.bech32Prefix) {
+ try {
+ const words = bech32.toWords(hexToBytes(hash));
+ return bech32.encode(config.UI.views.address.hashFormat.bech32Prefix, words);
+ } catch (error) {}
+ }
+
+ return hash;
+}
+
+export function isBech32Address(hash: string) {
+ if (!config.UI.views.address.hashFormat.bech32Prefix) {
+ return false;
+ }
+
+ if (!hash.startsWith(`${ config.UI.views.address.hashFormat.bech32Prefix }${ BECH_32_SEPARATOR }`)) {
+ return false;
+ }
+
+ const strippedHash = hash.replace(`${ config.UI.views.address.hashFormat.bech32Prefix }${ BECH_32_SEPARATOR }`, '');
+ return DATA_PART_REGEXP.test(strippedHash);
+}
+
+export function fromBech32Address(hash: string) {
+ if (config.UI.views.address.hashFormat.bech32Prefix) {
+ try {
+ const { words, prefix } = bech32.decode(hash as `${ string }${ typeof BECH_32_SEPARATOR }${ string }`);
+
+ if (prefix !== config.UI.views.address.hashFormat.bech32Prefix) {
+ return hash;
+ }
+
+ const bytes = bech32.fromWords(words);
+ return bytesToHex(bytes);
+ } catch (error) {}
+ }
+
+ return hash;
+}
diff --git a/explorer/frontend/lib/address/getCheckedSummedAddress.ts b/explorer/frontend/lib/address/getCheckedSummedAddress.ts
new file mode 100644
index 000000000..c3779744f
--- /dev/null
+++ b/explorer/frontend/lib/address/getCheckedSummedAddress.ts
@@ -0,0 +1,21 @@
+import { getAddress } from 'viem';
+
+import config from 'configs/app';
+
+const ERC1191_CHAIN_IDS = [
+ '30', // RSK Mainnet
+ '31', // RSK Testnet
+];
+
+export default function getCheckedSummedAddress(address: string): string {
+ try {
+ return getAddress(
+ address,
+ // We need to pass chainId to getAddress to make it work correctly for chains that support ERC-1191
+ // https://eips.ethereum.org/EIPS/eip-1191#usage--table
+ ERC1191_CHAIN_IDS.includes(config.chain.id ?? '') ? Number(config.chain.id) : undefined,
+ );
+ } catch (error) {
+ return address;
+ }
+}
diff --git a/explorer/frontend/lib/address/parseMetaPayload.ts b/explorer/frontend/lib/address/parseMetaPayload.ts
new file mode 100644
index 000000000..f8d6fbc57
--- /dev/null
+++ b/explorer/frontend/lib/address/parseMetaPayload.ts
@@ -0,0 +1,46 @@
+import type { AddressMetadataTag } from 'types/api/addressMetadata';
+import type { AddressMetadataTagFormatted } from 'types/client/addressMetadata';
+
+type MetaParsed = NonNullable;
+
+export default function parseMetaPayload(meta: AddressMetadataTag['meta']): AddressMetadataTagFormatted['meta'] {
+ try {
+ const parsedMeta = JSON.parse(meta || '');
+
+ if (typeof parsedMeta !== 'object' || parsedMeta === null || Array.isArray(parsedMeta)) {
+ throw new Error('Invalid JSON');
+ }
+
+ const result: AddressMetadataTagFormatted['meta'] = {};
+
+ const stringFields: Array = [
+ 'textColor',
+ 'bgColor',
+ 'tagIcon',
+ 'tagUrl',
+ 'tooltipIcon',
+ 'tooltipTitle',
+ 'tooltipDescription',
+ 'tooltipUrl',
+ 'appID',
+ 'appMarketplaceURL',
+ 'appLogoURL',
+ 'appActionButtonText',
+ 'warpcastHandle',
+ 'data',
+ 'alertBgColor',
+ 'alertTextColor',
+ 'alertStatus',
+ ];
+
+ for (const stringField of stringFields) {
+ if (stringField in parsedMeta && typeof parsedMeta[stringField as keyof typeof parsedMeta] === 'string') {
+ result[stringField] = parsedMeta[stringField as keyof typeof parsedMeta];
+ }
+ }
+
+ return result;
+ } catch (error) {
+ return null;
+ }
+}
diff --git a/explorer/frontend/lib/address/useAddressMetadataInfoQuery.ts b/explorer/frontend/lib/address/useAddressMetadataInfoQuery.ts
new file mode 100644
index 000000000..b6114c262
--- /dev/null
+++ b/explorer/frontend/lib/address/useAddressMetadataInfoQuery.ts
@@ -0,0 +1,35 @@
+import type { AddressMetadataInfoFormatted, AddressMetadataTagFormatted } from 'types/client/addressMetadata';
+
+import config from 'configs/app';
+import useApiQuery from 'lib/api/useApiQuery';
+
+import parseMetaPayload from './parseMetaPayload';
+
+export default function useAddressMetadataInfoQuery(addresses: Array, isEnabled = true) {
+
+ const resource = 'metadata:info';
+
+ return useApiQuery(resource, {
+ queryParams: {
+ addresses,
+ chainId: config.chain.id,
+ tagsLimit: '20',
+ },
+ queryOptions: {
+ enabled: isEnabled && addresses.length > 0 && config.features.addressMetadata.isEnabled,
+ select: (data) => {
+ const addresses = Object.entries(data.addresses)
+ .map(([ address, { tags, reputation } ]) => {
+ const formattedTags: Array = tags.map((tag) => ({ ...tag, meta: parseMetaPayload(tag.meta) }));
+ return [ address.toLowerCase(), { tags: formattedTags, reputation } ] as const;
+ })
+ .reduce((result, item) => {
+ result[item[0]] = item[1];
+ return result;
+ }, {} as AddressMetadataInfoFormatted['addresses']);
+
+ return { addresses };
+ },
+ },
+ });
+}
diff --git a/explorer/frontend/lib/api/buildUrl.test.ts b/explorer/frontend/lib/api/buildUrl.test.ts
new file mode 100644
index 000000000..c26d197a2
--- /dev/null
+++ b/explorer/frontend/lib/api/buildUrl.test.ts
@@ -0,0 +1,43 @@
+import buildUrl from './buildUrl';
+
+test('builds URL for resource without path params', () => {
+ const url = buildUrl('general:config_backend_version');
+ expect(url).toBe('https://localhost:3003/api/v2/config/backend-version');
+});
+
+test('builds URL for resource with path params', () => {
+ const url = buildUrl('general:block', { height_or_hash: '42' });
+ expect(url).toBe('https://localhost:3003/api/v2/blocks/42');
+});
+
+describe('falsy query parameters', () => {
+ test('leaves "false" as query parameter', () => {
+ const url = buildUrl('general:block', { height_or_hash: '42' }, { includeTx: false });
+ expect(url).toBe('https://localhost:3003/api/v2/blocks/42?includeTx=false');
+ });
+
+ test('leaves "null" as query parameter', () => {
+ const url = buildUrl('general:block', { height_or_hash: '42' }, { includeTx: null });
+ expect(url).toBe('https://localhost:3003/api/v2/blocks/42?includeTx=null');
+ });
+
+ test('strips out empty string as query parameter', () => {
+ const url = buildUrl('general:block', { height_or_hash: '42' }, { includeTx: null, sort: '' });
+ expect(url).toBe('https://localhost:3003/api/v2/blocks/42?includeTx=null');
+ });
+
+ test('strips out "undefined" as query parameter', () => {
+ const url = buildUrl('general:block', { height_or_hash: '42' }, { includeTx: null, sort: undefined });
+ expect(url).toBe('https://localhost:3003/api/v2/blocks/42?includeTx=null');
+ });
+});
+
+test('builds URL with array-like query parameters', () => {
+ const url = buildUrl('general:block', { height_or_hash: '42' }, { includeTx: [ '0x11', '0x22' ], sort: 'asc' });
+ expect(url).toBe('https://localhost:3003/api/v2/blocks/42?includeTx=0x11%2C0x22&sort=asc');
+});
+
+test('builds URL for resource with custom API endpoint', () => {
+ const url = buildUrl('contractInfo:token_verified_info', { chainId: '42', hash: '0x11' });
+ expect(url).toBe('https://localhost:3005/api/v1/chains/42/token-infos/0x11');
+});
diff --git a/explorer/frontend/lib/api/buildUrl.ts b/explorer/frontend/lib/api/buildUrl.ts
new file mode 100644
index 000000000..33bc8dca7
--- /dev/null
+++ b/explorer/frontend/lib/api/buildUrl.ts
@@ -0,0 +1,27 @@
+import { compile } from 'path-to-regexp';
+
+import config from 'configs/app';
+
+import getResourceParams from './getResourceParams';
+import isNeedProxy from './isNeedProxy';
+import type { ResourceName, ResourcePathParams } from './resources';
+
+export default function buildUrl(
+ resourceFullName: R,
+ pathParams?: ResourcePathParams,
+ queryParams?: Record | number | boolean | null | undefined>,
+ noProxy?: boolean,
+): string {
+ const { api, resource } = getResourceParams(resourceFullName);
+ const baseUrl = !noProxy && isNeedProxy() ? config.app.baseUrl : api.endpoint;
+ const basePath = api.basePath ?? '';
+ const path = !noProxy && isNeedProxy() ? '/node-api/proxy' + basePath + resource.path : basePath + resource.path;
+ const url = new URL(compile(path)(pathParams), baseUrl);
+
+ queryParams && Object.entries(queryParams).forEach(([ key, value ]) => {
+ // there are some pagination params that can be null or false for the next page
+ value !== undefined && value !== '' && url.searchParams.append(key, String(value));
+ });
+
+ return url.toString();
+}
diff --git a/explorer/frontend/lib/api/getResourceParams.ts b/explorer/frontend/lib/api/getResourceParams.ts
new file mode 100644
index 000000000..1dca71201
--- /dev/null
+++ b/explorer/frontend/lib/api/getResourceParams.ts
@@ -0,0 +1,21 @@
+import type { ApiName, ApiResource } from './types';
+
+import config from 'configs/app';
+
+import type { ResourceName } from './resources';
+import { RESOURCES } from './resources';
+
+export default function getResourceParams(resourceFullName: ResourceName) {
+ const [ apiName, resourceName ] = resourceFullName.split(':') as [ ApiName, string ];
+ const apiConfig = config.apis[apiName];
+
+ if (!apiConfig) {
+ throw new Error(`API config for ${ apiName } not found`);
+ }
+
+ return {
+ api: apiConfig,
+ apiName,
+ resource: RESOURCES[apiName][resourceName as keyof typeof RESOURCES[ApiName]] as ApiResource,
+ };
+}
diff --git a/explorer/frontend/lib/api/isBodyAllowed.ts b/explorer/frontend/lib/api/isBodyAllowed.ts
new file mode 100644
index 000000000..aad52fedb
--- /dev/null
+++ b/explorer/frontend/lib/api/isBodyAllowed.ts
@@ -0,0 +1,3 @@
+export default function isBodyAllowed(method: string | undefined | null) {
+ return method && ![ 'GET', 'HEAD' ].includes(method);
+}
diff --git a/explorer/frontend/lib/api/isNeedProxy.ts b/explorer/frontend/lib/api/isNeedProxy.ts
new file mode 100644
index 000000000..bd2089d67
--- /dev/null
+++ b/explorer/frontend/lib/api/isNeedProxy.ts
@@ -0,0 +1,13 @@
+import config from 'configs/app';
+
+// FIXME
+// I was not able to figure out how to send CORS with credentials from localhost
+// unsuccessfully tried different ways, even custom local dev domain
+// so for local development we have to use next.js api as proxy server
+export default function isNeedProxy() {
+ if (config.app.useProxy) {
+ return true;
+ }
+
+ return config.app.host === 'localhost' && config.app.host !== config.apis.general.host;
+}
diff --git a/explorer/frontend/lib/api/resources.ts b/explorer/frontend/lib/api/resources.ts
new file mode 100644
index 000000000..b25c1698c
--- /dev/null
+++ b/explorer/frontend/lib/api/resources.ts
@@ -0,0 +1,127 @@
+import type { ApiName, ApiResource } from './types';
+
+import type { AdminApiResourceName, AdminApiResourcePayload } from './services/admin';
+import { ADMIN_API_RESOURCES } from './services/admin';
+import { BENS_API_RESOURCES } from './services/bens';
+import type { BensApiResourceName, BensApiResourcePayload, BensApiPaginationFilters, BensApiPaginationSorting } from './services/bens';
+import { CHANNELS_API_RESOURCES } from './services/channels';
+import type { ChannelsApiResourceName, ChannelsApiResourcePayload } from './services/channels';
+import { CONTRACT_INFO_API_RESOURCES } from './services/contractInfo';
+import type { ContractInfoApiPaginationFilters, ContractInfoApiResourceName, ContractInfoApiResourcePayload } from './services/contractInfo';
+import { GENERAL_API_RESOURCES } from './services/general';
+import type { GeneralApiResourceName, GeneralApiResourcePayload, GeneralApiPaginationFilters, GeneralApiPaginationSorting } from './services/general';
+import type { MetadataApiResourceName, MetadataApiResourcePayload } from './services/metadata';
+import { METADATA_API_RESOURCES } from './services/metadata';
+import type { RewardsApiResourceName, RewardsApiResourcePayload } from './services/rewards';
+import { REWARDS_API_RESOURCES } from './services/rewards';
+import type { StatsApiResourceName, StatsApiResourcePayload } from './services/stats';
+import { STATS_API_RESOURCES } from './services/stats';
+import type { IsPaginated } from './services/utils';
+import { VISUALIZE_API_RESOURCES } from './services/visualize';
+import type { VisualizeApiResourceName, VisualizeApiResourcePayload } from './services/visualize';
+
+export const RESOURCES = {
+ admin: ADMIN_API_RESOURCES,
+ bens: BENS_API_RESOURCES,
+ channels: CHANNELS_API_RESOURCES,
+ contractInfo: CONTRACT_INFO_API_RESOURCES,
+ general: GENERAL_API_RESOURCES,
+ metadata: METADATA_API_RESOURCES,
+ rewards: REWARDS_API_RESOURCES,
+ stats: STATS_API_RESOURCES,
+ visualize: VISUALIZE_API_RESOURCES,
+} satisfies Record>;
+
+export const resourceKey = (x: ResourceName) => x;
+
+export type ResourceName = {
+ [K in keyof typeof RESOURCES]: `${ K & string }:${ keyof (typeof RESOURCES)[K] & string }`
+}[keyof typeof RESOURCES];
+
+export type ResourcePath = string;
+
+/* eslint-disable @stylistic/indent */
+export type ResourcePayload =
+R extends AdminApiResourceName ? AdminApiResourcePayload :
+R extends BensApiResourceName ? BensApiResourcePayload :
+R extends ChannelsApiResourceName ? ChannelsApiResourcePayload :
+R extends ContractInfoApiResourceName ? ContractInfoApiResourcePayload :
+R extends GeneralApiResourceName ? GeneralApiResourcePayload :
+R extends MetadataApiResourceName ? MetadataApiResourcePayload :
+R extends RewardsApiResourceName ? RewardsApiResourcePayload :
+R extends StatsApiResourceName ? StatsApiResourcePayload :
+R extends VisualizeApiResourceName ? VisualizeApiResourcePayload :
+never;
+/* eslint-enable @stylistic/indent */
+
+type ResourcePathParamName = Q extends `${ infer A }:${ infer R }` ?
+ (typeof RESOURCES)[A & keyof typeof RESOURCES][R & keyof (typeof RESOURCES)[A & keyof typeof RESOURCES]] extends { pathParams: Array } ?
+ (typeof RESOURCES)[A & keyof typeof RESOURCES][R & keyof (typeof RESOURCES)[A & keyof typeof RESOURCES]]['pathParams'][number] :
+ never :
+ never;
+
+export type ResourcePathParams = Q extends `${ infer A }:${ infer R }` ?
+ (typeof RESOURCES)[A & keyof typeof RESOURCES][R & keyof (typeof RESOURCES)[A & keyof typeof RESOURCES]] extends { pathParams: Array } ?
+ Record, string | undefined> :
+ never :
+ never;
+
+export interface ResourceError {
+ payload?: T;
+ status: Response['status'];
+ statusText: Response['statusText'];
+}
+
+export type ResourceErrorAccount = ResourceError<{ errors: T }>;
+
+// PAGINATION
+
+/* eslint-disable @stylistic/indent */
+export type PaginationFilters =
+R extends BensApiResourceName ? BensApiPaginationFilters :
+R extends GeneralApiResourceName ? GeneralApiPaginationFilters :
+R extends ContractInfoApiResourceName ? ContractInfoApiPaginationFilters :
+never;
+/* eslint-enable @stylistic/indent */
+
+export const SORTING_FIELDS = [ 'sort', 'order' ];
+
+/* eslint-disable @stylistic/indent */
+export type PaginationSorting =
+R extends BensApiResourceName ? BensApiPaginationSorting :
+R extends GeneralApiResourceName ? GeneralApiPaginationSorting :
+never;
+/* eslint-enable @stylistic/indent */
+
+export type PaginatedResourceName = {
+ [A in keyof typeof RESOURCES]: {
+ [R in keyof (typeof RESOURCES)[A]]: (typeof RESOURCES)[A][R] extends ApiResource ?
+ IsPaginated<(typeof RESOURCES)[A][R]> extends true ? `${ A & string }:${ R & string }` : never :
+ never
+ }[keyof (typeof RESOURCES)[A]]
+}[keyof typeof RESOURCES];
+
+export type PaginatedResourceResponse = ResourcePayload;
+
+export type PaginatedResourceResponseItems = R extends PaginatedResourceName ?
+ ResourcePayload['items'] :
+ never;
+
+export type PaginatedResourceResponseNextPageParams = R extends PaginatedResourceName ?
+ ResourcePayload['next_page_params'] :
+ never;
+
+// TESTS
+export const a: ResourcePayload<'general:api_keys'> = [ {
+ api_key: '123',
+ name: '123',
+} ];
+
+export const b: PaginatedResourceName = 'general:addresses';
+
+export const c: PaginatedResourceResponseItems<'general:addresses'> = [];
+
+export const d: ResourcePathParams<'bens:address_domain'> = {
+ chainId: '1',
+ address: '123',
+};
diff --git a/explorer/frontend/lib/api/services/admin.ts b/explorer/frontend/lib/api/services/admin.ts
new file mode 100644
index 000000000..15c61b4eb
--- /dev/null
+++ b/explorer/frontend/lib/api/services/admin.ts
@@ -0,0 +1,37 @@
+import type { ApiResource } from '../types';
+import type { TokenInfoApplicationConfig, TokenInfoApplications } from 'types/api/account';
+import type { MarketplaceAppOverview } from 'types/client/marketplace';
+
+export const ADMIN_API_RESOURCES = {
+ public_tag_application: {
+ path: '/api/v1/chains/:chainId/metadata-submissions/tag',
+ pathParams: [ 'chainId' as const ],
+ },
+ token_info_applications_config: {
+ path: '/api/v1/chains/:chainId/token-info-submissions/selectors',
+ pathParams: [ 'chainId' as const ],
+ },
+ token_info_applications: {
+ path: '/api/v1/chains/:chainId/token-info-submissions{/:id}',
+ pathParams: [ 'chainId' as const, 'id' as const ],
+ },
+ marketplace_dapps: {
+ path: '/api/v1/chains/:chainId/marketplace/dapps',
+ pathParams: [ 'chainId' as const ],
+ },
+ marketplace_dapp: {
+ path: '/api/v1/chains/:chainId/marketplace/dapps/:dappId',
+ pathParams: [ 'chainId' as const, 'dappId' as const ],
+ },
+} satisfies Record;
+
+export type AdminApiResourceName = `admin:${ keyof typeof ADMIN_API_RESOURCES }`;
+
+/* eslint-disable @stylistic/indent */
+export type AdminApiResourcePayload =
+R extends 'admin:token_info_applications_config' ? TokenInfoApplicationConfig :
+R extends 'admin:token_info_applications' ? TokenInfoApplications :
+R extends 'admin:marketplace_dapps' ? Array :
+R extends 'admin:marketplace_dapp' ? MarketplaceAppOverview :
+never;
+/* eslint-enable @stylistic/indent */
diff --git a/explorer/frontend/lib/api/services/bens.ts b/explorer/frontend/lib/api/services/bens.ts
new file mode 100644
index 000000000..7238b7744
--- /dev/null
+++ b/explorer/frontend/lib/api/services/bens.ts
@@ -0,0 +1,61 @@
+import type { ApiResource } from '../types';
+import type * as bens from '@blockscout/bens-types';
+import type { EnsAddressLookupFilters, EnsDomainLookupFilters, EnsLookupSorting } from 'types/api/ens';
+
+export const BENS_API_RESOURCES = {
+ addresses_lookup: {
+ path: '/api/v1/:chainId/addresses\\:lookup',
+ pathParams: [ 'chainId' as const ],
+ filterFields: [ 'address' as const, 'resolved_to' as const, 'owned_by' as const, 'only_active' as const, 'protocols' as const ],
+ paginated: true,
+ },
+ address_domain: {
+ path: '/api/v1/:chainId/addresses/:address',
+ pathParams: [ 'chainId' as const, 'address' as const ],
+ },
+ domain_info: {
+ path: '/api/v1/:chainId/domains/:name',
+ pathParams: [ 'chainId' as const, 'name' as const ],
+ },
+ domain_events: {
+ path: '/api/v1/:chainId/domains/:name/events',
+ pathParams: [ 'chainId' as const, 'name' as const ],
+ },
+ domains_lookup: {
+ path: '/api/v1/:chainId/domains\\:lookup',
+ pathParams: [ 'chainId' as const ],
+ filterFields: [ 'name' as const, 'only_active' as const, 'protocols' as const ],
+ paginated: true,
+ },
+ domain_protocols: {
+ path: '/api/v1/:chainId/protocols',
+ pathParams: [ 'chainId' as const ],
+ },
+} satisfies Record;
+
+export type BensApiResourceName = `bens:${ keyof typeof BENS_API_RESOURCES }`;
+
+/* eslint-disable @stylistic/indent */
+export type BensApiResourcePayload =
+R extends 'bens:addresses_lookup' ? bens.LookupAddressResponse :
+R extends 'bens:address_domain' ? bens.GetAddressResponse :
+R extends 'bens:domain_info' ? bens.DetailedDomain :
+R extends 'bens:domain_events' ? bens.ListDomainEventsResponse :
+R extends 'bens:domains_lookup' ? bens.LookupDomainNameResponse :
+R extends 'bens:domain_protocols' ? bens.GetProtocolsResponse :
+never;
+/* eslint-enable @stylistic/indent */
+
+/* eslint-disable @stylistic/indent */
+export type BensApiPaginationFilters =
+R extends 'bens:addresses_lookup' ? EnsAddressLookupFilters :
+R extends 'bens:domains_lookup' ? EnsDomainLookupFilters :
+never;
+/* eslint-enable @stylistic/indent */
+
+/* eslint-disable @stylistic/indent */
+export type BensApiPaginationSorting =
+R extends 'bens:addresses_lookup' ? EnsLookupSorting :
+R extends 'bens:domains_lookup' ? EnsLookupSorting :
+never;
+/* eslint-enable @stylistic/indent */
diff --git a/explorer/frontend/lib/api/services/channels.ts b/explorer/frontend/lib/api/services/channels.ts
new file mode 100644
index 000000000..d0eba15e4
--- /dev/null
+++ b/explorer/frontend/lib/api/services/channels.ts
@@ -0,0 +1,16 @@
+import type { ApiResource } from '../types';
+import type { SearchResultChannel } from 'types/api/search';
+
+export const CHANNELS_API_RESOURCES = {
+ search: {
+ path: '/api/channels',
+ },
+} satisfies Record;
+
+export type ChannelsApiResourceName = `channels:${keyof typeof CHANNELS_API_RESOURCES}`;
+
+/* eslint-disable @stylistic/indent */
+export type ChannelsApiResourcePayload =
+R extends 'channels:search' ? Array :
+never;
+/* eslint-enable @stylistic/indent */
\ No newline at end of file
diff --git a/explorer/frontend/lib/api/services/contractInfo.ts b/explorer/frontend/lib/api/services/contractInfo.ts
new file mode 100644
index 000000000..e0d67bd57
--- /dev/null
+++ b/explorer/frontend/lib/api/services/contractInfo.ts
@@ -0,0 +1,46 @@
+import type { ApiResource } from '../types';
+import type { VerifiedAddressResponse } from 'types/api/account';
+import type { Pool, PoolsResponse } from 'types/api/pools';
+import type { TokenVerifiedInfo } from 'types/api/token';
+
+export const CONTRACT_INFO_API_RESOURCES = {
+ address_verification: {
+ path: '/api/v1/chains/:chainId/verified-addresses:type',
+ pathParams: [ 'chainId' as const, 'type' as const ],
+ },
+ verified_addresses: {
+ path: '/api/v1/chains/:chainId/verified-addresses',
+ pathParams: [ 'chainId' as const ],
+ },
+ token_verified_info: {
+ path: '/api/v1/chains/:chainId/token-infos/:hash',
+ pathParams: [ 'chainId' as const, 'hash' as const ],
+ },
+ pools: {
+ path: '/api/v1/chains/:chainId/pools',
+ pathParams: [ 'chainId' as const ],
+ filterFields: [ 'query' as const ],
+ paginated: true,
+ },
+ pool: {
+ path: '/api/v1/chains/:chainId/pools/:hash',
+ pathParams: [ 'chainId' as const, 'hash' as const ],
+ },
+} satisfies Record;
+
+export type ContractInfoApiResourceName = `contractInfo:${ keyof typeof CONTRACT_INFO_API_RESOURCES }`;
+
+/* eslint-disable @stylistic/indent */
+export type ContractInfoApiResourcePayload =
+R extends 'contractInfo:verified_addresses' ? VerifiedAddressResponse :
+R extends 'contractInfo:token_verified_info' ? TokenVerifiedInfo :
+R extends 'contractInfo:pools' ? PoolsResponse :
+R extends 'contractInfo:pool' ? Pool :
+never;
+/* eslint-enable @stylistic/indent */
+
+/* eslint-disable @stylistic/indent */
+export type ContractInfoApiPaginationFilters =
+R extends 'contractInfo:pools' ? { query: string } :
+never;
+/* eslint-enable @stylistic/indent */
diff --git a/explorer/frontend/lib/api/services/general/account.ts b/explorer/frontend/lib/api/services/general/account.ts
new file mode 100644
index 000000000..0a4e8f44c
--- /dev/null
+++ b/explorer/frontend/lib/api/services/general/account.ts
@@ -0,0 +1,74 @@
+import type { ApiResource } from '../../types';
+import type { AddressTagsResponse, ApiKeys, CustomAbis, TransactionTagsResponse, UserInfo, WatchlistResponse } from 'types/api/account';
+
+export const GENERAL_API_ACCOUNT_RESOURCES = {
+ // ACCOUNT
+ csrf: {
+ path: '/api/account/v2/get_csrf',
+ },
+ user_info: {
+ path: '/api/account/v2/user/info',
+ },
+ custom_abi: {
+ path: '/api/account/v2/user/custom_abis{/:id}',
+ pathParams: [ 'id' as const ],
+ },
+ watchlist: {
+ path: '/api/account/v2/user/watchlist{/:id}',
+ pathParams: [ 'id' as const ],
+ filterFields: [ ],
+ paginated: true,
+ },
+ private_tags_address: {
+ path: '/api/account/v2/user/tags/address{/:id}',
+ pathParams: [ 'id' as const ],
+ filterFields: [ ],
+ paginated: true,
+ },
+ private_tags_tx: {
+ path: '/api/account/v2/user/tags/transaction{/:id}',
+ pathParams: [ 'id' as const ],
+ filterFields: [ ],
+ paginated: true,
+ },
+ api_keys: {
+ path: '/api/account/v2/user/api_keys{/:id}',
+ pathParams: [ 'id' as const ],
+ },
+
+ // AUTH
+ auth_send_otp: {
+ path: '/api/account/v2/send_otp',
+ },
+ auth_confirm_otp: {
+ path: '/api/account/v2/confirm_otp',
+ },
+ auth_siwe_message: {
+ path: '/api/account/v2/siwe_message',
+ },
+ auth_siwe_verify: {
+ path: '/api/account/v2/authenticate_via_wallet',
+ },
+ auth_link_email: {
+ path: '/api/account/v2/email/link',
+ },
+ auth_link_address: {
+ path: '/api/account/v2/address/link',
+ },
+ auth_logout: {
+ path: '/api/account/auth/logout',
+ },
+} satisfies Record;
+
+export type GeneralApiAccountResourceName = `general:${ keyof typeof GENERAL_API_ACCOUNT_RESOURCES }`;
+
+/* eslint-disable @stylistic/indent */
+export type GeneralApiAccountResourcePayload =
+R extends 'general:user_info' ? UserInfo :
+R extends 'general:custom_abi' ? CustomAbis :
+R extends 'general:private_tags_address' ? AddressTagsResponse :
+R extends 'general:private_tags_tx' ? TransactionTagsResponse :
+R extends 'general:api_keys' ? ApiKeys :
+R extends 'general:watchlist' ? WatchlistResponse :
+never;
+/* eslint-enable @stylistic/indent */
diff --git a/explorer/frontend/lib/api/services/general/address.ts b/explorer/frontend/lib/api/services/general/address.ts
new file mode 100644
index 000000000..e06cef624
--- /dev/null
+++ b/explorer/frontend/lib/api/services/general/address.ts
@@ -0,0 +1,170 @@
+import type { ApiResource } from '../../types';
+import type {
+ AddressCounters,
+ AddressBlocksValidatedResponse,
+ AddressTokensResponse,
+ AddressCollectionsResponse,
+ AddressEpochRewardsResponse,
+ AddressNFTsResponse,
+ AddressWithdrawalsResponse,
+ AddressXStarResponse,
+ AddressCoinBalanceHistoryChart,
+ AddressCoinBalanceHistoryResponse,
+ AddressTokenTransferResponse,
+ AddressInternalTxsResponse,
+ AddressTransactionsResponse,
+ AddressTabsCounters,
+ Address,
+ AddressTxsFilters,
+ AddressTokenTransferFilters,
+ AddressTokensFilter,
+ AddressNFTTokensFilter,
+} from 'types/api/address';
+import type { AddressesMetadataSearchFilters, AddressesMetadataSearchResult, AddressesResponse } from 'types/api/addresses';
+import type { LogsResponseAddress } from 'types/api/log';
+import type { TransactionsSorting } from 'types/api/transaction';
+
+export const GENERAL_API_ADDRESS_RESOURCES = {
+ // ADDRESSES
+ addresses: {
+ path: '/api/v2/addresses/',
+ filterFields: [ ],
+ paginated: true,
+ },
+ addresses_metadata_search: {
+ path: '/api/v2/proxy/metadata/addresses',
+ filterFields: [ 'slug' as const, 'tag_type' as const ],
+ paginated: true,
+ },
+
+ // ADDRESS INFO
+ address: {
+ path: '/api/v2/addresses/:hash',
+ pathParams: [ 'hash' as const ],
+ },
+ address_counters: {
+ path: '/api/v2/addresses/:hash/counters',
+ pathParams: [ 'hash' as const ],
+ },
+ address_tabs_counters: {
+ path: '/api/v2/addresses/:hash/tabs-counters',
+ pathParams: [ 'hash' as const ],
+ },
+ address_txs: {
+ path: '/api/v2/addresses/:hash/transactions',
+ pathParams: [ 'hash' as const ],
+ filterFields: [ 'filter' as const ],
+ paginated: true,
+ },
+ address_internal_txs: {
+ path: '/api/v2/addresses/:hash/internal-transactions',
+ pathParams: [ 'hash' as const ],
+ filterFields: [ 'filter' as const ],
+ paginated: true,
+ },
+ address_token_transfers: {
+ path: '/api/v2/addresses/:hash/token-transfers',
+ pathParams: [ 'hash' as const ],
+ filterFields: [ 'filter' as const, 'type' as const, 'token' as const ],
+ paginated: true,
+ },
+ address_blocks_validated: {
+ path: '/api/v2/addresses/:hash/blocks-validated',
+ pathParams: [ 'hash' as const ],
+ filterFields: [ ],
+ paginated: true,
+ },
+ address_coin_balance: {
+ path: '/api/v2/addresses/:hash/coin-balance-history',
+ pathParams: [ 'hash' as const ],
+ filterFields: [ ],
+ paginated: true,
+ },
+ address_coin_balance_chart: {
+ path: '/api/v2/addresses/:hash/coin-balance-history-by-day',
+ pathParams: [ 'hash' as const ],
+ filterFields: [ ],
+ },
+ address_logs: {
+ path: '/api/v2/addresses/:hash/logs',
+ pathParams: [ 'hash' as const ],
+ filterFields: [ ],
+ paginated: true,
+ },
+ address_tokens: {
+ path: '/api/v2/addresses/:hash/tokens',
+ pathParams: [ 'hash' as const ],
+ filterFields: [ 'type' as const ],
+ paginated: true,
+ },
+ address_nfts: {
+ path: '/api/v2/addresses/:hash/nft',
+ pathParams: [ 'hash' as const ],
+ filterFields: [ 'type' as const ],
+ paginated: true,
+ },
+ address_collections: {
+ path: '/api/v2/addresses/:hash/nft/collections',
+ pathParams: [ 'hash' as const ],
+ filterFields: [ 'type' as const ],
+ paginated: true,
+ },
+ address_withdrawals: {
+ path: '/api/v2/addresses/:hash/withdrawals',
+ pathParams: [ 'hash' as const ],
+ filterFields: [],
+ paginated: true,
+ },
+ address_epoch_rewards: {
+ path: '/api/v2/addresses/:hash/election-rewards',
+ pathParams: [ 'hash' as const ],
+ filterFields: [],
+ paginated: true,
+ },
+ address_xstar_score: {
+ path: '/api/v2/proxy/3dparty/xname/addresses/:hash',
+ pathParams: [ 'hash' as const ],
+ },
+} satisfies Record;
+
+export type GeneralApiAddressResourceName = `general:${ keyof typeof GENERAL_API_ADDRESS_RESOURCES }`;
+
+/* eslint-disable @stylistic/indent */
+export type GeneralApiAddressResourcePayload =
+R extends 'general:addresses' ? AddressesResponse :
+R extends 'general:addresses_metadata_search' ? AddressesMetadataSearchResult :
+R extends 'general:address' ? Address :
+R extends 'general:address_counters' ? AddressCounters :
+R extends 'general:address_tabs_counters' ? AddressTabsCounters :
+R extends 'general:address_txs' ? AddressTransactionsResponse :
+R extends 'general:address_internal_txs' ? AddressInternalTxsResponse :
+R extends 'general:address_token_transfers' ? AddressTokenTransferResponse :
+R extends 'general:address_blocks_validated' ? AddressBlocksValidatedResponse :
+R extends 'general:address_coin_balance' ? AddressCoinBalanceHistoryResponse :
+R extends 'general:address_coin_balance_chart' ? AddressCoinBalanceHistoryChart :
+R extends 'general:address_logs' ? LogsResponseAddress :
+R extends 'general:address_tokens' ? AddressTokensResponse :
+R extends 'general:address_nfts' ? AddressNFTsResponse :
+R extends 'general:address_collections' ? AddressCollectionsResponse :
+R extends 'general:address_withdrawals' ? AddressWithdrawalsResponse :
+R extends 'general:address_epoch_rewards' ? AddressEpochRewardsResponse :
+R extends 'general:address_xstar_score' ? AddressXStarResponse :
+never;
+/* eslint-enable @stylistic/indent */
+
+/* eslint-disable @stylistic/indent */
+export type GeneralApiAddressPaginationFilters =
+R extends 'general:addresses_metadata_search' ? AddressesMetadataSearchFilters :
+R extends 'general:address_txs' | 'general:address_internal_txs' ? AddressTxsFilters :
+R extends 'general:address_token_transfers' ? AddressTokenTransferFilters :
+R extends 'general:address_tokens' ? AddressTokensFilter :
+R extends 'general:address_nfts' ? AddressNFTTokensFilter :
+R extends 'general:address_collections' ? AddressNFTTokensFilter :
+never;
+/* eslint-enable @stylistic/indent */
+
+/* eslint-disable @stylistic/indent */
+export type GeneralApiAddressPaginationSorting =
+R extends 'general:address_txs' ? TransactionsSorting :
+never;
+/* eslint-enable @stylistic/indent */
diff --git a/explorer/frontend/lib/api/services/general/block.ts b/explorer/frontend/lib/api/services/general/block.ts
new file mode 100644
index 000000000..577dc2ecb
--- /dev/null
+++ b/explorer/frontend/lib/api/services/general/block.ts
@@ -0,0 +1,68 @@
+import type { ApiResource } from '../../types';
+import type {
+ BlocksResponse,
+ BlockTransactionsResponse,
+ Block,
+ BlockFilters,
+ BlockWithdrawalsResponse,
+ BlockCountdownResponse,
+ BlockEpoch,
+ BlockEpochElectionRewardDetailsResponse,
+} from 'types/api/block';
+import type { TTxsWithBlobsFilters } from 'types/api/txsFilters';
+
+export const GENERAL_API_BLOCK_RESOURCES = {
+ blocks: {
+ path: '/api/v2/blocks',
+ filterFields: [ 'type' as const ],
+ paginated: true,
+ },
+ block: {
+ path: '/api/v2/blocks/:height_or_hash',
+ pathParams: [ 'height_or_hash' as const ],
+ },
+ block_txs: {
+ path: '/api/v2/blocks/:height_or_hash/transactions',
+ pathParams: [ 'height_or_hash' as const ],
+ filterFields: [ 'type' as const ],
+ paginated: true,
+ },
+ block_withdrawals: {
+ path: '/api/v2/blocks/:height_or_hash/withdrawals',
+ pathParams: [ 'height_or_hash' as const ],
+ filterFields: [],
+ paginated: true,
+ },
+ block_epoch: {
+ path: '/api/v2/blocks/:height_or_hash/epoch',
+ pathParams: [ 'height_or_hash' as const ],
+ filterFields: [],
+ },
+ block_election_rewards: {
+ path: '/api/v2/blocks/:height_or_hash/election-rewards/:reward_type',
+ pathParams: [ 'height_or_hash' as const, 'reward_type' as const ],
+ filterFields: [],
+ paginated: true,
+ },
+} satisfies Record