Commit b6072dd4 authored by tom's avatar tom

Merge branch 'main' of github.com:blockscout/frontend into chakra-v3

parents 341acb38 540d95ee
...@@ -25,3 +25,7 @@ jobs: ...@@ -25,3 +25,7 @@ jobs:
name: Publish Docker image name: Publish Docker image
uses: './.github/workflows/publish-image.yml' uses: './.github/workflows/publish-image.yml'
secrets: inherit secrets: inherit
with:
tags: |
type=ref,event=branch
type=raw,value=unstable
...@@ -21,6 +21,7 @@ on: ...@@ -21,6 +21,7 @@ on:
- eth_sepolia - eth_sepolia
- eth_goerli - eth_goerli
- filecoin - filecoin
- neon_devnet
- optimism - optimism
- optimism_celestia - optimism_celestia
- optimism_sepolia - optimism_sepolia
...@@ -53,7 +54,8 @@ jobs: ...@@ -53,7 +54,8 @@ jobs:
needs: make_slug needs: make_slug
uses: './.github/workflows/publish-image.yml' uses: './.github/workflows/publish-image.yml'
with: with:
tags: ghcr.io/blockscout/frontend:review-${{ needs.make_slug.outputs.REF_SLUG }} tags: |
type=raw,value=review-${{ needs.make_slug.outputs.REF_SLUG }}
build_args: ENVS_PRESET=${{ inputs.envs_preset }} build_args: ENVS_PRESET=${{ inputs.envs_preset }}
secrets: inherit secrets: inherit
......
...@@ -21,10 +21,13 @@ on: ...@@ -21,10 +21,13 @@ on:
- eth_sepolia - eth_sepolia
- eth_goerli - eth_goerli
- filecoin - filecoin
- mekong
- neon_devnet
- optimism - optimism
- optimism_celestia - optimism_celestia
- optimism_sepolia - optimism_sepolia
- polygon - polygon
- rari_testnet
- rootstock - rootstock
- shibarium - shibarium
- scroll_sepolia - scroll_sepolia
...@@ -53,7 +56,8 @@ jobs: ...@@ -53,7 +56,8 @@ jobs:
needs: make_slug needs: make_slug
uses: './.github/workflows/publish-image.yml' uses: './.github/workflows/publish-image.yml'
with: with:
tags: ghcr.io/blockscout/frontend:review-${{ needs.make_slug.outputs.REF_SLUG }} tags: |
type=raw,value=review-${{ needs.make_slug.outputs.REF_SLUG }}
build_args: ENVS_PRESET=${{ inputs.envs_preset }} build_args: ENVS_PRESET=${{ inputs.envs_preset }}
secrets: inherit secrets: inherit
......
...@@ -13,6 +13,10 @@ jobs: ...@@ -13,6 +13,10 @@ jobs:
name: Publish Docker image name: Publish Docker image
uses: './.github/workflows/publish-image.yml' uses: './.github/workflows/publish-image.yml'
secrets: inherit secrets: inherit
with:
# NOTE: by default the image will be built with type=ref,event=tag; so we don't need to specify it here
tags: |
type=raw,value=e2e
deploy_e2e: deploy_e2e:
name: Deploy E2E instance name: Deploy E2E instance
......
...@@ -4,7 +4,7 @@ on: ...@@ -4,7 +4,7 @@ on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
tags: tags:
description: Image tags description: Image tags (e.g. "type=raw,value=foo")
required: false required: false
type: string type: string
build_args: build_args:
...@@ -19,7 +19,7 @@ on: ...@@ -19,7 +19,7 @@ on:
workflow_call: workflow_call:
inputs: inputs:
tags: tags:
description: Image tags description: Image tags (e.g. "type=raw,value=foo")
required: false required: false
type: string type: string
build_args: build_args:
...@@ -49,6 +49,11 @@ jobs: ...@@ -49,6 +49,11 @@ jobs:
uses: docker/metadata-action@v5 uses: docker/metadata-action@v5
with: with:
images: ghcr.io/blockscout/frontend images: ghcr.io/blockscout/frontend
flavor: |
latest=false
tags: |
type=ref,event=tag
${{ inputs.tags }}
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
uses: docker/login-action@v2 uses: docker/login-action@v2
...@@ -75,7 +80,7 @@ jobs: ...@@ -75,7 +80,7 @@ jobs:
file: ./Dockerfile file: ./Dockerfile
push: true push: true
cache-from: type=gha cache-from: type=gha
tags: ${{ inputs.tags || steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
platforms: ${{ inputs.platforms }} platforms: ${{ inputs.platforms }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
build-args: | build-args: |
......
...@@ -80,6 +80,9 @@ jobs: ...@@ -80,6 +80,9 @@ jobs:
secrets: inherit secrets: inherit
with: with:
platforms: linux/amd64,linux/arm64/v8 platforms: linux/amd64,linux/arm64/v8
# NOTE: by default the image will be built with type=ref,event=tag; so we need to specify it here
tags: |
type=raw,value=latest
sync_envs_docs: sync_envs_docs:
name: Sync ENV variables docs name: Sync ENV variables docs
......
...@@ -369,10 +369,12 @@ ...@@ -369,10 +369,12 @@
"eth_goerli", "eth_goerli",
"eth_sepolia", "eth_sepolia",
"filecoin", "filecoin",
"mekong",
"optimism", "optimism",
"optimism_celestia", "optimism_celestia",
"optimism_sepolia", "optimism_sepolia",
"polygon", "polygon",
"rari_testnet",
"rootstock_testnet", "rootstock_testnet",
"shibarium", "shibarium",
"stability_testnet", "stability_testnet",
......
import type { Feature } from './types';
import type { TxExternalTxsConfig } from 'types/client/externalTxsConfig';
import { getEnvValue, parseEnvJson } from '../utils';
const externalTransactionsConfig = parseEnvJson<TxExternalTxsConfig>(getEnvValue('NEXT_PUBLIC_TX_EXTERNAL_TRANSACTIONS_CONFIG'));
const title = 'External transactions';
const config: Feature<{ chainName: string; chainLogoUrl: string; explorerUrlTemplate: string }> = (() => {
if (externalTransactionsConfig) {
return Object.freeze({
title,
isEnabled: true,
chainName: externalTransactionsConfig.chain_name,
chainLogoUrl: externalTransactionsConfig.chain_logo_url,
explorerUrlTemplate: externalTransactionsConfig.explorer_url_template,
});
}
return Object.freeze({
title,
isEnabled: false,
});
})();
export default config;
...@@ -12,6 +12,7 @@ export { default as csvExport } from './csvExport'; ...@@ -12,6 +12,7 @@ export { default as csvExport } from './csvExport';
export { default as dataAvailability } from './dataAvailability'; export { default as dataAvailability } from './dataAvailability';
export { default as deFiDropdown } from './deFiDropdown'; export { default as deFiDropdown } from './deFiDropdown';
export { default as easterEggBadge } from './easterEggBadge'; export { default as easterEggBadge } from './easterEggBadge';
export { default as externalTxs } from './externalTxs';
export { default as faultProofSystem } from './faultProofSystem'; export { default as faultProofSystem } from './faultProofSystem';
export { default as gasTracker } from './gasTracker'; export { default as gasTracker } from './gasTracker';
export { default as getGasButton } from './getGasButton'; export { default as getGasButton } from './getGasButton';
......
import type { Feature } from './types'; import type { Feature } from './types';
import type { RollupType } from 'types/client/rollup'; import type { ParentChain, RollupType } from 'types/client/rollup';
import { ROLLUP_TYPES } from 'types/client/rollup'; import { ROLLUP_TYPES } from 'types/client/rollup';
import stripTrailingSlash from 'lib/stripTrailingSlash'; import stripTrailingSlash from 'lib/stripTrailingSlash';
import { getEnvValue } from '../utils'; import { getEnvValue, parseEnvJson } from '../utils';
const type = (() => { const type = (() => {
const envValue = getEnvValue('NEXT_PUBLIC_ROLLUP_TYPE'); const envValue = getEnvValue('NEXT_PUBLIC_ROLLUP_TYPE');
return ROLLUP_TYPES.find((type) => type === envValue); return ROLLUP_TYPES.find((type) => type === envValue);
})(); })();
const L1BaseUrl = getEnvValue('NEXT_PUBLIC_ROLLUP_L1_BASE_URL');
const L2WithdrawalUrl = getEnvValue('NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL'); const L2WithdrawalUrl = getEnvValue('NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL');
const parentChain: ParentChain | undefined = (() => {
const envValue = parseEnvJson<ParentChain>(getEnvValue('NEXT_PUBLIC_ROLLUP_PARENT_CHAIN'));
const baseUrl = stripTrailingSlash(getEnvValue('NEXT_PUBLIC_ROLLUP_L1_BASE_URL') || '');
const chainName = getEnvValue('NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME');
if (!baseUrl && !envValue?.baseUrl) {
return;
}
return {
...envValue,
name: chainName ?? envValue?.name,
baseUrl: baseUrl ?? envValue?.baseUrl,
};
})();
const title = 'Rollup (L2) chain'; const title = 'Rollup (L2) chain';
const config: Feature<{ const config: Feature<{
type: RollupType; type: RollupType;
L1BaseUrl: string;
homepage: { showLatestBlocks: boolean }; homepage: { showLatestBlocks: boolean };
outputRootsEnabled: boolean; outputRootsEnabled: boolean;
L2WithdrawalUrl: string | undefined; L2WithdrawalUrl: string | undefined;
parentChainName: string | undefined; parentChain: ParentChain;
DA: {
celestia: {
namespace: string | undefined;
};
};
}> = (() => { }> = (() => {
if (type && L1BaseUrl) { if (type && parentChain) {
return Object.freeze({ return Object.freeze({
title, title,
isEnabled: true, isEnabled: true,
type, type,
L1BaseUrl: stripTrailingSlash(L1BaseUrl),
L2WithdrawalUrl: type === 'optimistic' ? L2WithdrawalUrl : undefined, L2WithdrawalUrl: type === 'optimistic' ? L2WithdrawalUrl : undefined,
outputRootsEnabled: type === 'optimistic' && getEnvValue('NEXT_PUBLIC_ROLLUP_OUTPUT_ROOTS_ENABLED') === 'true', outputRootsEnabled: type === 'optimistic' && getEnvValue('NEXT_PUBLIC_ROLLUP_OUTPUT_ROOTS_ENABLED') === 'true',
parentChainName: type === 'arbitrum' ? getEnvValue('NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME') : undefined,
homepage: { homepage: {
showLatestBlocks: getEnvValue('NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS') === 'true', showLatestBlocks: getEnvValue('NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS') === 'true',
}, },
parentChain,
DA: {
celestia: {
namespace: type === 'arbitrum' ? getEnvValue('NEXT_PUBLIC_ROLLUP_DA_CELESTIA_NAMESPACE') : undefined,
},
},
}); });
} }
......
export { default as address } from './address'; export { default as address } from './address';
export { default as block } from './block'; export { default as block } from './block';
export { default as nft } from './nft'; export { default as nft } from './nft';
export { default as token } from './token';
export { default as tx } from './tx'; export { default as tx } from './tx';
import { getEnvValue } from 'configs/app/utils';
const config = Object.freeze({
hideScamTokensEnabled: getEnvValue('NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED') === 'true',
});
export default config;
...@@ -9,6 +9,8 @@ NEXT_PUBLIC_APP_PORT=3000 ...@@ -9,6 +9,8 @@ NEXT_PUBLIC_APP_PORT=3000
NEXT_PUBLIC_APP_ENV=development NEXT_PUBLIC_APP_ENV=development
NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
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']}
# Instance ENVs # Instance ENVs
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
NEXT_PUBLIC_API_BASE_PATH=/ NEXT_PUBLIC_API_BASE_PATH=/
...@@ -16,13 +18,27 @@ NEXT_PUBLIC_API_HOST=arbitrum.blockscout.com ...@@ -16,13 +18,27 @@ 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_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_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_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swap','icon':'swap','dappId':'swoop-exchange'},{'text':'Disperse','icon':'txn_batches_slim','dappId':'smol'},{'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/arbitrum-one.json
NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x37c798810d49ba132b40efe7f4fdf6806a8fc58226bb5e185ddc91f896577abf NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x37c798810d49ba132b40efe7f4fdf6806a8fc58226bb5e185ddc91f896577abf
NEXT_PUBLIC_HAS_CONTRACT_AUDIT_REPORTS=true
NEXT_PUBLIC_HAS_USER_OPS=true
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs'] NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND=rgba(27, 74, 221, 1) NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['rgba(27, 74, 221, 1)']}
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
NEXT_PUBLIC_LOGOUT_URL=https://blockscout-arbitrum.us.auth0.com/v2/logout NEXT_PUBLIC_LOGOUT_URL=https://blockscout-arbitrum.us.auth0.com/v2/logout
NEXT_PUBLIC_MARKETPLACE_ENABLED=false NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE=<p>Joined recent campaigns? Mint your Merit Badge <a href="https://badges.blockscout.com?utm_source=instance&utm_medium=arbitrum">here</a></p>
NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL=https://gist.githubusercontent.com/maikReal/974c47f86a3158c1a86b092ae2f044b3/raw/abcc7e02150cd85d4974503a0357162c0a2c35a9/merits-banner.html
NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL=https://swap.blockscout.com?utm_source=blockscout&utm_medium=arbitrum
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_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_DECIMALS=18
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=ETH NEXT_PUBLIC_NETWORK_CURRENCY_NAME=ETH
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
...@@ -33,12 +49,15 @@ NEXT_PUBLIC_NETWORK_ID=42161 ...@@ -33,12 +49,15 @@ 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=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_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_NAME=Arbitrum One
NEXT_PUBLIC_NETWORK_RPC_URL=https://arbitrum.llamarpc.com NEXT_PUBLIC_NETWORK_RPC_URL=https://arbitrum-one.publicnode.com
NEXT_PUBLIC_NETWORK_SHORT_NAME=Arbitrum One NEXT_PUBLIC_NETWORK_SHORT_NAME=Arbitrum One
NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true 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_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_L1_BASE_URL=https://eth.blockscout.com
NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME=Ethereum
NEXT_PUBLIC_ROLLUP_TYPE=arbitrum NEXT_PUBLIC_ROLLUP_TYPE=arbitrum
NEXT_PUBLIC_STATS_API_HOST=https://stats-arbitrum-one-nitro.k8s-prod-2.blockscout.com
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file 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
...@@ -41,7 +41,8 @@ NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true ...@@ -41,7 +41,8 @@ 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_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_L1_BASE_URL=https://eth-sepolia.blockscout.com
NEXT_PUBLIC_ROLLUP_TYPE=arbitrum NEXT_PUBLIC_ROLLUP_TYPE=arbitrum
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_SENTRY_DSN=https://fdcd971162e04694bf03564c5be3d291@o1222505.ingest.sentry.io/4503902500421632 NEXT_PUBLIC_SENTRY_DSN=https://fdcd971162e04694bf03564c5be3d291@o1222505.ingest.sentry.io/4503902500421632
NEXT_PUBLIC_STATS_API_HOST=https://stats-arbitrum-sepolia.k8s-prod-2.blockscout.com NEXT_PUBLIC_STATS_API_HOST=https://stats-arbitrum-sepolia.k8s-prod-2.blockscout.com
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
...@@ -10,6 +10,8 @@ NEXT_PUBLIC_APP_ENV=development ...@@ -10,6 +10,8 @@ NEXT_PUBLIC_APP_ENV=development
NEXT_PUBLIC_APP_INSTANCE=rubber_duck NEXT_PUBLIC_APP_INSTANCE=rubber_duck
NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
# Instance ENVs # Instance ENVs
NEXT_PUBLIC_AD_ADBUTLER_CONFIG_DESKTOP={ "id": "632019", "width": "728", "height": "90" } 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_ADBUTLER_CONFIG_MOBILE={ "id": "632018", "width": "320", "height": "100" }
......
# 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_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_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_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
# 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_HOST=https://stats-neon-devnet.k8s.blockscout.com
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
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}'}
# 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_SHORT_NAME=Rari Testnet
NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=false
NEXT_PUBLIC_OTHER_LINKS=[]
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
NEXT_PUBLIC_ROLLUP_DA_CELESTIA_NAMESPACE=0x00000000000000000000000000000000000000ca1de12a9905be97beaf
\ No newline at end of file
...@@ -9,14 +9,12 @@ NEXT_PUBLIC_APP_PORT=3000 ...@@ -9,14 +9,12 @@ NEXT_PUBLIC_APP_PORT=3000
NEXT_PUBLIC_APP_ENV=development NEXT_PUBLIC_APP_ENV=development
NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
NEXT_PUBLIC_VIEWS_CONTRACT_LANGUAGE_FILTERS=['solidity','vyper','yul','scilla']
# Instance ENVs # Instance ENVs
NEXT_PUBLIC_API_BASE_PATH=/ NEXT_PUBLIC_API_BASE_PATH=/
NEXT_PUBLIC_API_HOST=zilliqa-prototestnet.blockscout.com 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_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_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_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x3d1ded3a7924cd3256a4b1a447c9bfb194f54b9a8ceb441edb8bb01563b516db NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x3d1ded3a7924cd3256a4b1a447c9bfb194f54b9a8ceb441edb8bb01563b516db
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs'] 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_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)']}}}
...@@ -38,4 +36,6 @@ NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-c ...@@ -38,4 +36,6 @@ NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-c
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
NEXT_PUBLIC_VIEWS_ADDRESS_BECH_32_PREFIX=zil NEXT_PUBLIC_VIEWS_ADDRESS_BECH_32_PREFIX=zil
NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT=["base16", "bech32"] NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT=["base16", "bech32"]
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com NEXT_PUBLIC_VIEWS_CONTRACT_LANGUAGE_FILTERS=['solidity','vyper','yul','scilla']
\ No newline at end of file NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE=zilliqa
\ No newline at end of file
...@@ -157,6 +157,16 @@ function printDeprecationWarning(envsMap: Record<string, string>) { ...@@ -157,6 +157,16 @@ function printDeprecationWarning(envsMap: Record<string, string>) {
console.log('❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗\n'); console.log('❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗\n');
} }
if (
envsMap.NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME ||
envsMap.NEXT_PUBLIC_ROLLUP_L1_BASE_URL
) {
console.log('❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗');
// 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.');
console.log('❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗\n');
}
if ( if (
envsMap.NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR || envsMap.NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR ||
envsMap.NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND envsMap.NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND
......
...@@ -43,6 +43,7 @@ import type { NftMarketplaceItem } from '../../../types/views/nft'; ...@@ -43,6 +43,7 @@ import type { NftMarketplaceItem } from '../../../types/views/nft';
import type { TxAdditionalFieldsId, TxFieldsId } from '../../../types/views/tx'; import type { TxAdditionalFieldsId, TxFieldsId } from '../../../types/views/tx';
import { TX_ADDITIONAL_FIELDS_IDS, TX_FIELDS_IDS } 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 { VerifiedContractsFilter } from '../../../types/api/contracts';
import type { TxExternalTxsConfig } from '../../../types/client/externalTxsConfig';
import { replaceQuotes } from '../../../configs/app/utils'; import { replaceQuotes } from '../../../configs/app/utils';
import * as regexp from '../../../lib/regexp'; import * as regexp from '../../../lib/regexp';
...@@ -70,6 +71,14 @@ const urlTest: yup.TestConfig = { ...@@ -70,6 +71,14 @@ const urlTest: yup.TestConfig = {
exclusive: true, 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<MarketplaceAppOverview> = yup const marketplaceAppSchema: yup.ObjectSchema<MarketplaceAppOverview> = yup
.object({ .object({
id: yup.string().required(), id: yup.string().required(),
...@@ -270,6 +279,44 @@ const beaconChainSchema = yup ...@@ -270,6 +279,44 @@ const beaconChainSchema = yup
}), }),
}); });
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 const rollupSchema = yup
.object() .object()
.shape({ .shape({
...@@ -321,6 +368,44 @@ const rollupSchema = yup ...@@ -321,6 +368,44 @@ const rollupSchema = yup
value => value === undefined, 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\' '),
}),
}); });
const celoSchema = yup const celoSchema = yup
...@@ -563,6 +648,12 @@ const multichainProviderConfigSchema: yup.ObjectSchema<MultichainProviderConfig> ...@@ -563,6 +648,12 @@ const multichainProviderConfigSchema: yup.ObjectSchema<MultichainProviderConfig>
dapp_id: yup.string(), dapp_id: yup.string(),
}); });
const externalTxsConfigSchema: yup.ObjectSchema<TxExternalTxsConfig> = yup.object({
chain_name: yup.string().required(),
chain_logo_url: yup.string().required(),
explorer_url_template: yup.string().required(),
});
const schema = yup const schema = yup
.object() .object()
.noUnknown(true, (params) => { .noUnknown(true, (params) => {
...@@ -635,12 +726,34 @@ const schema = yup ...@@ -635,12 +726,34 @@ const schema = yup
.array() .array()
.transform(replaceQuotes) .transform(replaceQuotes)
.json() .json()
.of(yup.string<ChainIndicatorId>().oneOf(CHAIN_INDICATOR_IDS)), .of(yup.string<ChainIndicatorId>().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 NEXT_PUBLIC_HOMEPAGE_STATS: yup
.array() .array()
.transform(replaceQuotes) .transform(replaceQuotes)
.json() .json()
.of(yup.string<HomeStatsWidgetId>().oneOf(HOME_STATS_WIDGET_IDS)), .of(yup.string<HomeStatsWidgetId>().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_TEXT_COLOR: yup.string(),
NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND: yup.string(), NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND: yup.string(),
NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG: yup NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG: yup
...@@ -652,7 +765,7 @@ const schema = yup ...@@ -652,7 +765,7 @@ const schema = yup
heroBannerSchema.validateSync(ctx.originalValue); heroBannerSchema.validateSync(ctx.originalValue);
throw new Error('Unknown validation error'); throw new Error('Unknown validation error');
} catch (error: unknown) { } catch (error: unknown) {
const message = typeof error === 'object' && error !== null && 'errors' in error && Array.isArray(error.errors) ? error.errors.join(', ') : ''; const message = getYupValidationErrorMessage(error);
return 'Invalid schema were provided for NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG' + (message ? `: ${ message }` : ''); return 'Invalid schema were provided for NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG' + (message ? `: ${ message }` : '');
} }
}, },
...@@ -755,6 +868,7 @@ const schema = yup ...@@ -755,6 +868,7 @@ const schema = yup
.transform(replaceQuotes) .transform(replaceQuotes)
.json() .json()
.of(nftMarketplaceSchema), .of(nftMarketplaceSchema),
NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED: yup.boolean(),
NEXT_PUBLIC_HELIA_VERIFIED_FETCH_ENABLED: yup.boolean(), NEXT_PUBLIC_HELIA_VERIFIED_FETCH_ENABLED: yup.boolean(),
// e. misc // e. misc
...@@ -912,6 +1026,19 @@ const schema = yup ...@@ -912,6 +1026,19 @@ const schema = yup
NEXT_PUBLIC_REWARDS_SERVICE_API_HOST: yup.string().test(urlTest), NEXT_PUBLIC_REWARDS_SERVICE_API_HOST: yup.string().test(urlTest),
NEXT_PUBLIC_XSTAR_SCORE_URL: 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_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<TxExternalTxsConfig>().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 // 6. External services envs
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: yup.string(), NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: yup.string(),
......
NEXT_PUBLIC_ROLLUP_TYPE=arbitrum NEXT_PUBLIC_ROLLUP_TYPE=arbitrum
NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://example.com NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://example.com
NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS=true NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS=true
NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME=DuckChain NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME=DuckChain
\ No newline at end of file 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
\ No newline at end of file
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
...@@ -3,4 +3,5 @@ NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://example.com ...@@ -3,4 +3,5 @@ NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://example.com
NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL=https://example.com NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL=https://example.com
NEXT_PUBLIC_FAULT_PROOF_ENABLED=true NEXT_PUBLIC_FAULT_PROOF_ENABLED=true
NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS=true NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS=true
NEXT_PUBLIC_ROLLUP_OUTPUT_ROOTS_ENABLED=false NEXT_PUBLIC_ROLLUP_OUTPUT_ROOTS_ENABLED=false
\ No newline at end of file NEXT_PUBLIC_ROLLUP_PARENT_CHAIN={'baseUrl':'https://explorer.duckchain.io'}
...@@ -78,6 +78,7 @@ frontend: ...@@ -78,6 +78,7 @@ frontend:
NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES: "['/apps']" NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES: "['/apps']"
PROMETHEUS_METRICS_ENABLED: true PROMETHEUS_METRICS_ENABLED: true
NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED: true NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED: true
NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED: true
envFromSecret: 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_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_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
......
...@@ -4,6 +4,16 @@ Thanks for showing interest to contribute to Blockscout. The following steps wil ...@@ -4,6 +4,16 @@ Thanks for showing interest to contribute to Blockscout. The following steps wil
&nbsp; &nbsp;
## 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.
&nbsp;
## Project setup ## Project setup
1. Fork the repo by clicking <kbd>Fork</kbd> button at the top of the repo main page and name it appropriately 1. Fork the repo by clicking <kbd>Fork</kbd> button at the top of the repo main page and name it appropriately
......
...@@ -126,8 +126,8 @@ Please be aware that all environment variables prefixed with `NEXT_PUBLIC_` will ...@@ -126,8 +126,8 @@ Please be aware that all environment variables prefixed with `NEXT_PUBLIC_` will
| Variable | Type| Description | Compulsoriness | Default value | Example value | Version | | Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
| --- | --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- | --- | --- |
| NEXT_PUBLIC_HOMEPAGE_CHARTS | `Array<'daily_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_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' \| '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_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_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_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+ | | 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+ |
...@@ -280,6 +280,13 @@ Settings for meta tags, OG tags and SEO ...@@ -280,6 +280,13 @@ Settings for meta tags, OG tags and SEO
&nbsp; &nbsp;
#### 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. | - | - | `'["value","tx_fee"]'` | v1.38.0+ |
&nbsp;
#### NFT views #### NFT views
| Variable | Type | Description | Compulsoriness | Default value | Example value | Version | | Variable | Type | Description | Compulsoriness | Default value | Example value | Version |
...@@ -450,13 +457,27 @@ This feature is **enabled by default** with the `coinzilla` ads provider. To swi ...@@ -450,13 +457,27 @@ This feature is **enabled by default** with the `coinzilla` ads provider. To swi
| Variable | Type| Description | Compulsoriness | Default value | Example value | Version | | 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_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 | Required | - | `'http://eth-goerli.blockscout.com'` | 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_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_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_HAS_MUD_FRAMEWORK | `boolean` | Set to `true` for instances that use MUD framework (Optimistic stack only) | - | - | `true` | v1.33.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_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_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 <chain-name>"). This setting is applicable only for Arbitrum-based chains. | - | - | `DuckChain` | v1.37.0+ | | NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME | `string` | Set to customize L1 transaction status labels in the UI (e.g., "Sent to <chain-name>"). 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+ |
#### 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 <chain-name>"). 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<string>` | 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` |
&nbsp; &nbsp;
...@@ -590,6 +611,14 @@ This feature is **enabled by default** with the `['metamask']` value. To switch ...@@ -590,6 +611,14 @@ This feature is **enabled by default** with the `['metamask']` value. To switch
&nbsp; &nbsp;
### 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+ |
&nbsp;
### Verified tokens info ### Verified tokens info
| Variable | Type| Description | Compulsoriness | Default value | Example value | Version | | Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
...@@ -749,7 +778,7 @@ The feature enables the Validators page which provides detailed information abou ...@@ -749,7 +778,7 @@ The feature enables the Validators page which provides detailed information abou
| Variable | Type| Description | Compulsoriness | Default value | Example value | Version | | Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
| --- | --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- | --- | --- |
| NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE | `'stability' \| 'blackfort'` | Chain type | Required | - | `'stability'` | v1.25.0+ | | NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE | `'stability' \| 'blackfort' \| 'zilliqa'` | Chain type | Required | - | `'stability'` | v1.25.0+ |
&nbsp; &nbsp;
......
...@@ -42,6 +42,11 @@ const RESTRICTED_MODULES = { ...@@ -42,6 +42,11 @@ const RESTRICTED_MODULES = {
], ],
message: 'Please use corresponding component or hook from ui/shared/chakra component instead', message: 'Please use corresponding component or hook from ui/shared/chakra component instead',
}, },
{
name: 'next/link',
importNames: [ 'default' ],
message: 'Please use ui/shared/NextLink component instead',
},
], ],
patterns: [ patterns: [
'icons/*', 'icons/*',
......
<svg viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="m5.29 9.053 3.723-3.828a.972.972 0 0 1 1.336.06 1.051 1.051 0 0 1 .058 1.394L8.4 8.751h14.37c.262 0 .514.107.7.3.188.191.294.454.294.729 0 .275-.106.537-.293.73a.976.976 0 0 1-.7.298H5.987a.969.969 0 0 1-.55-.17 1.02 1.02 0 0 1-.367-.46 1.062 1.062 0 0 1 .22-1.125Zm18.724 6a.97.97 0 0 1 .55.17c.163.111.291.271.367.46a1.062 1.062 0 0 1-.22 1.125l-3.737 3.841-.006.008a.997.997 0 0 1-.322.255.966.966 0 0 1-1.13-.197 1.06 1.06 0 0 1 .056-1.513l.008-.006 2.021-2.087H15.72c.103-.684.183-1.403 0-2.072l8.294.016Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="m5.29 9.053 3.723-3.828a.972.972 0 0 1 1.336.06 1.051 1.051 0 0 1 .058 1.394L8.4 8.751h14.37c.262 0 .514.107.7.3.188.191.294.454.294.729 0 .275-.106.537-.293.73a.976.976 0 0 1-.7.298H5.987a.969.969 0 0 1-.55-.17 1.02 1.02 0 0 1-.367-.46 1.062 1.062 0 0 1 .22-1.125Zm18.724 6a.97.97 0 0 1 .55.17c.163.111.291.271.367.46a1.062 1.062 0 0 1-.22 1.125l-3.737 3.841-.006.008a.997.997 0 0 1-.322.255.966.966 0 0 1-1.13-.197 1.06 1.06 0 0 1 .056-1.513l.008-.006 2.021-2.087H15.72c.103-.684.183-1.403 0-2.072l8.294.016ZM6.209 13.24a.67.67 0 0 1 .504-.24h4.277c.095 0 .186.043.252.12l2.496 2.865c.067.077.104.181.104.29v6.55a.884.884 0 0 1-.209.578.67.67 0 0 1-.504.24H6.713a.67.67 0 0 1-.504-.24.884.884 0 0 1-.209-.579V13.82c0-.217.075-.426.209-.58Zm4.634.579h-4.13v9.005h6.416v-6.38l-2.286-2.625Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.209 13.24a.67.67 0 0 1 .504-.24h4.277c.095 0 .186.043.252.12l2.496 2.865c.067.077.104.181.104.29v6.55a.884.884 0 0 1-.209.578.67.67 0 0 1-.504.24H6.713a.67.67 0 0 1-.504-.24.884.884 0 0 1-.209-.579V13.82c0-.217.075-.426.209-.58Zm4.634.579h-4.13v9.005h6.416v-6.38l-2.286-2.625Z" fill="currentColor"/>
<path clip-rule="evenodd" d="M6.209 13.24a.67.67 0 0 1 .504-.24h4.277c.095 0 .186.043.252.12l2.496 2.865c.067.077.104.181.104.29v6.55a.884.884 0 0 1-.209.578.67.67 0 0 1-.504.24H6.713a.67.67 0 0 1-.504-.24.884.884 0 0 1-.209-.579V13.82c0-.217.075-.426.209-.58Zm4.634.579h-4.13v9.005h6.416v-6.38l-2.286-2.625Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path clip-rule="evenodd" d="M6.209 13.24a.67.67 0 0 1 .504-.24h4.277c.095 0 .186.043.252.12l2.496 2.865c.067.077.104.181.104.29v6.55a.884.884 0 0 1-.209.578.67.67 0 0 1-.504.24H6.713a.67.67 0 0 1-.504-.24.884.884 0 0 1-.209-.579V13.82c0-.217.075-.426.209-.58Zm4.634.579h-4.13v9.005h6.416v-6.38l-2.286-2.625Z" stroke="currentColor" stroke-opacity=".2" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.743 13.224c.206 0 .373.167.373.373v2.24h2.24a.373.373 0 1 1 0 .748h-2.613a.373.373 0 0 1-.374-.374v-2.614c0-.206.167-.373.374-.373Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.743 13.224c.206 0 .373.167.373.373v2.24h2.24a.373.373 0 1 1 0 .748h-2.613a.373.373 0 0 1-.374-.374v-2.614c0-.206.167-.373.374-.373Z" fill="currentColor"/>
<path clip-rule="evenodd" d="M10.743 13.224c.206 0 .373.167.373.373v2.24h2.24a.373.373 0 1 1 0 .748h-2.613a.373.373 0 0 1-.374-.374v-2.614c0-.206.167-.373.374-.373Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path clip-rule="evenodd" d="M10.743 13.224c.206 0 .373.167.373.373v2.24h2.24a.373.373 0 1 1 0 .748h-2.613a.373.373 0 0 1-.374-.374v-2.614c0-.206.167-.373.374-.373Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
...@@ -18,6 +18,7 @@ const PAGE_PROPS = { ...@@ -18,6 +18,7 @@ const PAGE_PROPS = {
query: {}, query: {},
adBannerProvider: null, adBannerProvider: null,
apiData: null, apiData: null,
uuid: '123',
}; };
const TestApp = ({ children }: { children: React.ReactNode }) => { const TestApp = ({ children }: { children: React.ReactNode }) => {
......
This diff is collapsed.
...@@ -20,10 +20,26 @@ export default function useQueryClientConfig() { ...@@ -20,10 +20,26 @@ export default function useQueryClientConfig() {
queries: { queries: {
refetchOnWindowFocus: false, refetchOnWindowFocus: false,
retry, retry,
throwOnError: (error) => { throwOnError: (error, query) => {
const status = getErrorObjStatusCode(error); const status = getErrorObjStatusCode(error);
// don't catch error for "Too many requests" response
return status === 429; // we don't catch error only for "Too many requests" response
if (status !== 429) {
return false;
}
const EXTERNAL_API_RESOURCES = [
'safe_transaction_api',
'contract_solidity_scan_report',
'address_xstar_score',
'noves_transaction',
'noves_address_history',
'noves_describe_txs',
'gas_hawk_saving_potential',
];
const isExternalApiResource = EXTERNAL_API_RESOURCES.some((resource) => query.queryKey[0] === resource);
return !isExternalApiResource;
}, },
}, },
}, },
......
...@@ -14,6 +14,7 @@ const AppContext = createContext<PageProps>({ ...@@ -14,6 +14,7 @@ const AppContext = createContext<PageProps>({
query: {}, query: {},
adBannerProvider: null, adBannerProvider: null,
apiData: null, apiData: null,
uuid: '',
}); });
export function AppContextProvider({ children, pageProps }: Props) { export function AppContextProvider({ children, pageProps }: Props) {
......
...@@ -44,6 +44,7 @@ type TRewardsContext = { ...@@ -44,6 +44,7 @@ type TRewardsContext = {
isLoginModalOpen: boolean; isLoginModalOpen: boolean;
openLoginModal: () => void; openLoginModal: () => void;
closeLoginModal: () => void; closeLoginModal: () => void;
saveApiToken: (token: string | undefined) => void;
login: (refCode: string) => Promise<{ isNewUser?: boolean; invalidRefCodeError?: boolean }>; login: (refCode: string) => Promise<{ isNewUser?: boolean; invalidRefCodeError?: boolean }>;
claim: () => Promise<void>; claim: () => Promise<void>;
}; };
...@@ -68,6 +69,7 @@ const initialState = { ...@@ -68,6 +69,7 @@ const initialState = {
isLoginModalOpen: false, isLoginModalOpen: false,
openLoginModal: () => {}, openLoginModal: () => {},
closeLoginModal: () => {}, closeLoginModal: () => {},
saveApiToken: () => {},
login: async() => ({}), login: async() => ({}),
claim: async() => {}, claim: async() => {},
}; };
...@@ -268,6 +270,7 @@ export function RewardsContextProvider({ children }: Props) { ...@@ -268,6 +270,7 @@ export function RewardsContextProvider({ children }: Props) {
rewardsConfigQuery, rewardsConfigQuery,
checkUserQuery, checkUserQuery,
apiToken, apiToken,
saveApiToken,
isInitialized, isInitialized,
isLoginModalOpen, isLoginModalOpen,
openLoginModal, openLoginModal,
...@@ -277,7 +280,7 @@ export function RewardsContextProvider({ children }: Props) { ...@@ -277,7 +280,7 @@ export function RewardsContextProvider({ children }: Props) {
}; };
}, [ }, [
balancesQuery, dailyRewardQuery, checkUserQuery, balancesQuery, dailyRewardQuery, checkUserQuery,
apiToken, login, claim, referralsQuery, rewardsConfigQuery, isInitialized, apiToken, login, claim, referralsQuery, rewardsConfigQuery, isInitialized, saveApiToken,
isLoginModalOpen, openLoginModal, closeLoginModal, isLoginModalOpen, openLoginModal, closeLoginModal,
]); ]);
......
...@@ -17,6 +17,7 @@ export enum NAMES { ...@@ -17,6 +17,7 @@ export enum NAMES {
MIXPANEL_DEBUG = '_mixpanel_debug', MIXPANEL_DEBUG = '_mixpanel_debug',
ADDRESS_NFT_DISPLAY_TYPE = 'address_nft_display_type', ADDRESS_NFT_DISPLAY_TYPE = 'address_nft_display_type',
UUID = 'uuid', UUID = 'uuid',
SHOW_SCAM_TOKENS = 'show_scam_tokens',
} }
export function get(name?: NAMES | undefined | null, serverCookie?: string) { export function get(name?: NAMES | undefined | null, serverCookie?: string) {
......
import getErrorObj from './getErrorObj';
export default function getErrorProp<T extends unknown>(error: unknown, prop: string): T | undefined {
const errorObj = getErrorObj(error);
return errorObj && prop in errorObj ?
(errorObj[prop as keyof typeof errorObj] as T) :
undefined;
}
...@@ -9,7 +9,7 @@ export interface GrowthBookFeatures { ...@@ -9,7 +9,7 @@ export interface GrowthBookFeatures {
test_value: string; test_value: string;
} }
export const growthBook = (() => { export const initGrowthBook = (uuid: string) => {
const feature = config.features.growthBook; const feature = config.features.growthBook;
if (!feature.isEnabled) { if (!feature.isEnabled) {
...@@ -21,7 +21,7 @@ export const growthBook = (() => { ...@@ -21,7 +21,7 @@ export const growthBook = (() => {
clientKey: feature.clientKey, clientKey: feature.clientKey,
enableDevMode: config.app.isDev, enableDevMode: config.app.isDev,
attributes: { attributes: {
id: mixpanel.getUuid(), id: uuid,
chain_id: config.chain.id, chain_id: config.chain.id,
}, },
trackingCallback: (experiment, result) => { trackingCallback: (experiment, result) => {
...@@ -37,7 +37,7 @@ export const growthBook = (() => { ...@@ -37,7 +37,7 @@ export const growthBook = (() => {
}); });
}, },
}); });
})(); };
function getStorageValue(): Array<unknown> | undefined { function getStorageValue(): Array<unknown> | undefined {
const item = window.localStorage.getItem(STORAGE_KEY); const item = window.localStorage.getItem(STORAGE_KEY);
......
...@@ -2,9 +2,10 @@ import React from 'react'; ...@@ -2,9 +2,10 @@ import React from 'react';
import { SECOND } from 'lib/consts'; import { SECOND } from 'lib/consts';
import { growthBook } from './init'; import { initGrowthBook } from './init';
export default function useLoadFeatures() { export default function useLoadFeatures(uuid: string) {
const growthBook = initGrowthBook(uuid);
React.useEffect(() => { React.useEffect(() => {
growthBook?.setAttributes({ growthBook?.setAttributes({
...growthBook.getAttributes(), ...growthBook.getAttributes(),
...@@ -13,5 +14,5 @@ export default function useLoadFeatures() { ...@@ -13,5 +14,5 @@ export default function useLoadFeatures() {
}); });
growthBook?.loadFeatures({ timeout: SECOND }); growthBook?.loadFeatures({ timeout: SECOND });
}, []); }, [ growthBook ]);
} }
...@@ -44,6 +44,12 @@ export default function useNavItems(): ReturnType { ...@@ -44,6 +44,12 @@ export default function useNavItems(): ReturnType {
icon: 'transactions', icon: 'transactions',
isActive: pathname === '/txs' || pathname === '/tx/[hash]', isActive: pathname === '/txs' || pathname === '/tx/[hash]',
}; };
const internalTxs: NavItem | null = {
text: 'Internal transactions',
nextRoute: { pathname: '/internal-txs' as const },
icon: 'internal_txns',
isActive: pathname === '/internal-txs',
};
const userOps: NavItem | null = config.features.userOps.isEnabled ? { const userOps: NavItem | null = config.features.userOps.isEnabled ? {
text: 'User operations', text: 'User operations',
nextRoute: { pathname: '/ops' as const }, nextRoute: { pathname: '/ops' as const },
...@@ -68,7 +74,7 @@ export default function useNavItems(): ReturnType { ...@@ -68,7 +74,7 @@ export default function useNavItems(): ReturnType {
text: 'Top validators', text: 'Top validators',
nextRoute: { pathname: '/validators' as const }, nextRoute: { pathname: '/validators' as const },
icon: 'validator', icon: 'validator',
isActive: pathname === '/validators', isActive: pathname === '/validators' || pathname === '/validators/[id]',
} : null; } : null;
const rollupDeposits = { const rollupDeposits = {
text: `Deposits (L1${ rightLineArrow }L2)`, text: `Deposits (L1${ rightLineArrow }L2)`,
...@@ -118,6 +124,7 @@ export default function useNavItems(): ReturnType { ...@@ -118,6 +124,7 @@ export default function useNavItems(): ReturnType {
blockchainNavItems = [ blockchainNavItems = [
[ [
txs, txs,
internalTxs,
rollupDeposits, rollupDeposits,
rollupWithdrawals, rollupWithdrawals,
], ],
...@@ -140,6 +147,7 @@ export default function useNavItems(): ReturnType { ...@@ -140,6 +147,7 @@ export default function useNavItems(): ReturnType {
blockchainNavItems = [ blockchainNavItems = [
[ [
txs, txs,
internalTxs,
rollupDeposits, rollupDeposits,
rollupWithdrawals, rollupWithdrawals,
], ],
...@@ -155,6 +163,7 @@ export default function useNavItems(): ReturnType { ...@@ -155,6 +163,7 @@ export default function useNavItems(): ReturnType {
blockchainNavItems = [ blockchainNavItems = [
[ [
txs, txs,
internalTxs,
userOps, userOps,
blocks, blocks,
rollupTxnBatches, rollupTxnBatches,
...@@ -169,6 +178,7 @@ export default function useNavItems(): ReturnType { ...@@ -169,6 +178,7 @@ export default function useNavItems(): ReturnType {
} else { } else {
blockchainNavItems = [ blockchainNavItems = [
txs, txs,
internalTxs,
userOps, userOps,
blocks, blocks,
topAccounts, topAccounts,
...@@ -246,6 +256,11 @@ export default function useNavItems(): ReturnType { ...@@ -246,6 +256,11 @@ export default function useNavItems(): ReturnType {
nextRoute: { pathname: '/public-tags/submit' as const }, nextRoute: { pathname: '/public-tags/submit' as const },
isActive: pathname.startsWith('/public-tags/submit'), isActive: pathname.startsWith('/public-tags/submit'),
}, },
rollupFeature.isEnabled && rollupFeature.type === 'arbitrum' && {
text: 'Txn withdrawals',
nextRoute: { pathname: '/txn-withdrawals' as const },
isActive: pathname.startsWith('/txn-withdrawals'),
},
...config.UI.navigation.otherLinks, ...config.UI.navigation.otherLinks,
].filter(Boolean); ].filter(Boolean);
......
...@@ -5,6 +5,7 @@ type OGPageType = 'Homepage' | 'Root page' | 'Regular page'; ...@@ -5,6 +5,7 @@ type OGPageType = 'Homepage' | 'Root page' | 'Regular page';
const OG_TYPE_DICT: Record<Route['pathname'], OGPageType> = { const OG_TYPE_DICT: Record<Route['pathname'], OGPageType> = {
'/': 'Homepage', '/': 'Homepage',
'/txs': 'Root page', '/txs': 'Root page',
'/internal-txs': 'Root page',
'/txs/kettle/[hash]': 'Regular page', '/txs/kettle/[hash]': 'Regular page',
'/tx/[hash]': 'Regular page', '/tx/[hash]': 'Regular page',
'/blocks': 'Root page', '/blocks': 'Root page',
...@@ -28,7 +29,7 @@ const OG_TYPE_DICT: Record<Route['pathname'], OGPageType> = { ...@@ -28,7 +29,7 @@ const OG_TYPE_DICT: Record<Route['pathname'], OGPageType> = {
'/graphiql': 'Regular page', '/graphiql': 'Regular page',
'/search-results': 'Regular page', '/search-results': 'Regular page',
'/auth/profile': 'Root page', '/auth/profile': 'Root page',
'/account/rewards': 'Regular page', '/account/merits': 'Regular page',
'/account/watchlist': 'Regular page', '/account/watchlist': 'Regular page',
'/account/api-key': 'Regular page', '/account/api-key': 'Regular page',
'/account/custom-abi': 'Regular page', '/account/custom-abi': 'Regular page',
...@@ -36,6 +37,7 @@ const OG_TYPE_DICT: Record<Route['pathname'], OGPageType> = { ...@@ -36,6 +37,7 @@ const OG_TYPE_DICT: Record<Route['pathname'], OGPageType> = {
'/account/verified-addresses': 'Root page', '/account/verified-addresses': 'Root page',
'/public-tags/submit': 'Regular page', '/public-tags/submit': 'Regular page',
'/withdrawals': 'Root page', '/withdrawals': 'Root page',
'/txn-withdrawals': 'Root page',
'/visualize/sol2uml': 'Regular page', '/visualize/sol2uml': 'Regular page',
'/csv-export': 'Regular page', '/csv-export': 'Regular page',
'/deposits': 'Root page', '/deposits': 'Root page',
...@@ -43,6 +45,7 @@ const OG_TYPE_DICT: Record<Route['pathname'], OGPageType> = { ...@@ -43,6 +45,7 @@ const OG_TYPE_DICT: Record<Route['pathname'], OGPageType> = {
'/dispute-games': 'Root page', '/dispute-games': 'Root page',
'/batches': 'Root page', '/batches': 'Root page',
'/batches/[number]': 'Regular page', '/batches/[number]': 'Regular page',
'/batches/celestia/[height]/[commitment]': 'Regular page',
'/blobs/[hash]': 'Regular page', '/blobs/[hash]': 'Regular page',
'/ops': 'Root page', '/ops': 'Root page',
'/op/[hash]': 'Regular page', '/op/[hash]': 'Regular page',
...@@ -50,6 +53,7 @@ const OG_TYPE_DICT: Record<Route['pathname'], OGPageType> = { ...@@ -50,6 +53,7 @@ const OG_TYPE_DICT: Record<Route['pathname'], OGPageType> = {
'/name-domains': 'Root page', '/name-domains': 'Root page',
'/name-domains/[name]': 'Regular page', '/name-domains/[name]': 'Regular page',
'/validators': 'Root page', '/validators': 'Root page',
'/validators/[id]': 'Regular page',
'/gas-tracker': 'Root page', '/gas-tracker': 'Root page',
'/mud-worlds': 'Root page', '/mud-worlds': 'Root page',
'/token-transfers': 'Root page', '/token-transfers': 'Root page',
......
...@@ -8,6 +8,7 @@ const DEFAULT_TEMPLATE = 'Open-source block explorer by Blockscout. Search trans ...@@ -8,6 +8,7 @@ const DEFAULT_TEMPLATE = 'Open-source block explorer by Blockscout. Search trans
const TEMPLATE_MAP: Record<Route['pathname'], string> = { const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/': DEFAULT_TEMPLATE, '/': DEFAULT_TEMPLATE,
'/txs': DEFAULT_TEMPLATE, '/txs': DEFAULT_TEMPLATE,
'/internal-txs': DEFAULT_TEMPLATE,
'/txs/kettle/[hash]': DEFAULT_TEMPLATE, '/txs/kettle/[hash]': DEFAULT_TEMPLATE,
'/tx/[hash]': 'View transaction %hash% on %network_title%', '/tx/[hash]': 'View transaction %hash% on %network_title%',
'/blocks': DEFAULT_TEMPLATE, '/blocks': DEFAULT_TEMPLATE,
...@@ -31,7 +32,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = { ...@@ -31,7 +32,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/graphiql': DEFAULT_TEMPLATE, '/graphiql': DEFAULT_TEMPLATE,
'/search-results': DEFAULT_TEMPLATE, '/search-results': DEFAULT_TEMPLATE,
'/auth/profile': DEFAULT_TEMPLATE, '/auth/profile': DEFAULT_TEMPLATE,
'/account/rewards': DEFAULT_TEMPLATE, '/account/merits': DEFAULT_TEMPLATE,
'/account/watchlist': DEFAULT_TEMPLATE, '/account/watchlist': DEFAULT_TEMPLATE,
'/account/api-key': DEFAULT_TEMPLATE, '/account/api-key': DEFAULT_TEMPLATE,
'/account/custom-abi': DEFAULT_TEMPLATE, '/account/custom-abi': DEFAULT_TEMPLATE,
...@@ -39,6 +40,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = { ...@@ -39,6 +40,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/account/verified-addresses': DEFAULT_TEMPLATE, '/account/verified-addresses': DEFAULT_TEMPLATE,
'/public-tags/submit': 'Propose a new public tag for your address, contract or set of contracts for your dApp. Our team will review and approve your submission. Public tags are incredible tool which helps users identify contracts and addresses.', '/public-tags/submit': 'Propose a new public tag for your address, contract or set of contracts for your dApp. Our team will review and approve your submission. Public tags are incredible tool which helps users identify contracts and addresses.',
'/withdrawals': DEFAULT_TEMPLATE, '/withdrawals': DEFAULT_TEMPLATE,
'/txn-withdrawals': DEFAULT_TEMPLATE,
'/visualize/sol2uml': DEFAULT_TEMPLATE, '/visualize/sol2uml': DEFAULT_TEMPLATE,
'/csv-export': DEFAULT_TEMPLATE, '/csv-export': DEFAULT_TEMPLATE,
'/deposits': DEFAULT_TEMPLATE, '/deposits': DEFAULT_TEMPLATE,
...@@ -46,6 +48,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = { ...@@ -46,6 +48,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/dispute-games': DEFAULT_TEMPLATE, '/dispute-games': DEFAULT_TEMPLATE,
'/batches': DEFAULT_TEMPLATE, '/batches': DEFAULT_TEMPLATE,
'/batches/[number]': DEFAULT_TEMPLATE, '/batches/[number]': DEFAULT_TEMPLATE,
'/batches/celestia/[height]/[commitment]': DEFAULT_TEMPLATE,
'/blobs/[hash]': DEFAULT_TEMPLATE, '/blobs/[hash]': DEFAULT_TEMPLATE,
'/ops': DEFAULT_TEMPLATE, '/ops': DEFAULT_TEMPLATE,
'/op/[hash]': DEFAULT_TEMPLATE, '/op/[hash]': DEFAULT_TEMPLATE,
...@@ -53,6 +56,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = { ...@@ -53,6 +56,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/name-domains': DEFAULT_TEMPLATE, '/name-domains': DEFAULT_TEMPLATE,
'/name-domains/[name]': DEFAULT_TEMPLATE, '/name-domains/[name]': DEFAULT_TEMPLATE,
'/validators': DEFAULT_TEMPLATE, '/validators': DEFAULT_TEMPLATE,
'/validators/[id]': DEFAULT_TEMPLATE,
'/gas-tracker': 'Explore real-time %network_title% gas fees with Blockscout\'s advanced gas fee tracker. Get accurate %network_gwei% estimates and track transaction costs live.', '/gas-tracker': 'Explore real-time %network_title% gas fees with Blockscout\'s advanced gas fee tracker. Get accurate %network_gwei% estimates and track transaction costs live.',
'/mud-worlds': DEFAULT_TEMPLATE, '/mud-worlds': DEFAULT_TEMPLATE,
'/token-transfers': DEFAULT_TEMPLATE, '/token-transfers': DEFAULT_TEMPLATE,
......
...@@ -5,6 +5,7 @@ import config from 'configs/app'; ...@@ -5,6 +5,7 @@ import config from 'configs/app';
const TEMPLATE_MAP: Record<Route['pathname'], string> = { const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/': '%network_name% blockchain explorer - View %network_name% stats', '/': '%network_name% blockchain explorer - View %network_name% stats',
'/txs': '%network_name% transactions - %network_name% explorer', '/txs': '%network_name% transactions - %network_name% explorer',
'/internal-txs': '%network_name% internal transactions - %network_name% explorer',
'/txs/kettle/[hash]': '%network_name% kettle %hash% transactions', '/txs/kettle/[hash]': '%network_name% kettle %hash% transactions',
'/tx/[hash]': '%network_name% transaction %hash%', '/tx/[hash]': '%network_name% transaction %hash%',
'/blocks': '%network_name% blocks', '/blocks': '%network_name% blocks',
...@@ -28,7 +29,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = { ...@@ -28,7 +29,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/graphiql': 'GraphQL for %network_name% - %network_name% data query', '/graphiql': 'GraphQL for %network_name% - %network_name% data query',
'/search-results': '%network_name% search result for %q%', '/search-results': '%network_name% search result for %q%',
'/auth/profile': '%network_name% - my profile', '/auth/profile': '%network_name% - my profile',
'/account/rewards': '%network_name% - rewards', '/account/merits': '%network_name% - Merits',
'/account/watchlist': '%network_name% - watchlist', '/account/watchlist': '%network_name% - watchlist',
'/account/api-key': '%network_name% - API keys', '/account/api-key': '%network_name% - API keys',
'/account/custom-abi': '%network_name% - custom ABI', '/account/custom-abi': '%network_name% - custom ABI',
...@@ -36,6 +37,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = { ...@@ -36,6 +37,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/account/verified-addresses': '%network_name% - my verified addresses', '/account/verified-addresses': '%network_name% - my verified addresses',
'/public-tags/submit': '%network_name% - public tag requests', '/public-tags/submit': '%network_name% - public tag requests',
'/withdrawals': '%network_name% withdrawals - track on %network_name% explorer', '/withdrawals': '%network_name% withdrawals - track on %network_name% explorer',
'/txn-withdrawals': '%network_name% L2 to L1 message relayer',
'/visualize/sol2uml': '%network_name% Solidity UML diagram', '/visualize/sol2uml': '%network_name% Solidity UML diagram',
'/csv-export': '%network_name% export data to CSV', '/csv-export': '%network_name% export data to CSV',
'/deposits': '%network_name% deposits (L1 > L2)', '/deposits': '%network_name% deposits (L1 > L2)',
...@@ -43,6 +45,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = { ...@@ -43,6 +45,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/dispute-games': '%network_name% dispute games', '/dispute-games': '%network_name% dispute games',
'/batches': '%network_name% txn batches', '/batches': '%network_name% txn batches',
'/batches/[number]': '%network_name% L2 txn batch %number%', '/batches/[number]': '%network_name% L2 txn batch %number%',
'/batches/celestia/[height]/[commitment]': '%network_name% L2 txn batch %height% %commitment%',
'/blobs/[hash]': '%network_name% blob %hash% details', '/blobs/[hash]': '%network_name% blob %hash% details',
'/ops': 'User operations on %network_name% - %network_name% explorer', '/ops': 'User operations on %network_name% - %network_name% explorer',
'/op/[hash]': '%network_name% user operation %hash%', '/op/[hash]': '%network_name% user operation %hash%',
...@@ -50,6 +53,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = { ...@@ -50,6 +53,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/name-domains': '%network_name% name domains - %network_name% explorer', '/name-domains': '%network_name% name domains - %network_name% explorer',
'/name-domains/[name]': '%network_name% %name% domain details', '/name-domains/[name]': '%network_name% %name% domain details',
'/validators': '%network_name% validators list', '/validators': '%network_name% validators list',
'/validators/[id]': '%network_name% validator %id% details',
'/gas-tracker': 'Track %network_name% gas fees in %network_gwei%', '/gas-tracker': 'Track %network_name% gas fees in %network_gwei%',
'/mud-worlds': '%network_name% MUD worlds list', '/mud-worlds': '%network_name% MUD worlds list',
'/token-transfers': '%network_name% token transfers', '/token-transfers': '%network_name% token transfers',
......
...@@ -3,6 +3,7 @@ import type { Route } from 'nextjs-routes'; ...@@ -3,6 +3,7 @@ import type { Route } from 'nextjs-routes';
export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = { export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = {
'/': 'Homepage', '/': 'Homepage',
'/txs': 'Transactions', '/txs': 'Transactions',
'/internal-txs': 'Internal transactions',
'/txs/kettle/[hash]': 'Kettle transactions', '/txs/kettle/[hash]': 'Kettle transactions',
'/tx/[hash]': 'Transaction details', '/tx/[hash]': 'Transaction details',
'/blocks': 'Blocks', '/blocks': 'Blocks',
...@@ -26,7 +27,7 @@ export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = { ...@@ -26,7 +27,7 @@ export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = {
'/graphiql': 'GraphQL', '/graphiql': 'GraphQL',
'/search-results': 'Search results', '/search-results': 'Search results',
'/auth/profile': 'Profile', '/auth/profile': 'Profile',
'/account/rewards': 'Merits', '/account/merits': 'Merits',
'/account/watchlist': 'Watchlist', '/account/watchlist': 'Watchlist',
'/account/api-key': 'API keys', '/account/api-key': 'API keys',
'/account/custom-abi': 'Custom ABI', '/account/custom-abi': 'Custom ABI',
...@@ -34,6 +35,7 @@ export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = { ...@@ -34,6 +35,7 @@ export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = {
'/account/verified-addresses': 'Verified addresses', '/account/verified-addresses': 'Verified addresses',
'/public-tags/submit': 'Submit public tag', '/public-tags/submit': 'Submit public tag',
'/withdrawals': 'Withdrawals', '/withdrawals': 'Withdrawals',
'/txn-withdrawals': 'Txn withdrawals',
'/visualize/sol2uml': 'Solidity UML diagram', '/visualize/sol2uml': 'Solidity UML diagram',
'/csv-export': 'Export data to CSV file', '/csv-export': 'Export data to CSV file',
'/deposits': 'Deposits (L1 > L2)', '/deposits': 'Deposits (L1 > L2)',
...@@ -41,6 +43,7 @@ export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = { ...@@ -41,6 +43,7 @@ export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = {
'/dispute-games': 'Dispute games', '/dispute-games': 'Dispute games',
'/batches': 'Txn batches', '/batches': 'Txn batches',
'/batches/[number]': 'L2 txn batch details', '/batches/[number]': 'L2 txn batch details',
'/batches/celestia/[height]/[commitment]': 'L2 txn batch details',
'/blobs/[hash]': 'Blob details', '/blobs/[hash]': 'Blob details',
'/ops': 'User operations', '/ops': 'User operations',
'/op/[hash]': 'User operation details', '/op/[hash]': 'User operation details',
...@@ -48,6 +51,7 @@ export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = { ...@@ -48,6 +51,7 @@ export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = {
'/name-domains': 'Domains search and resolve', '/name-domains': 'Domains search and resolve',
'/name-domains/[name]': 'Domain details', '/name-domains/[name]': 'Domain details',
'/validators': 'Validators list', '/validators': 'Validators list',
'/validators/[id]': 'Validator details',
'/gas-tracker': 'Gas tracker', '/gas-tracker': 'Gas tracker',
'/mud-worlds': 'MUD worlds', '/mud-worlds': 'MUD worlds',
'/token-transfers': 'Token transfers', '/token-transfers': 'Token transfers',
......
import * as cookies from 'lib/cookies';
import * as growthBook from 'lib/growthbook/consts';
import isBrowser from 'lib/isBrowser';
export default function getUuid() {
const cookie = cookies.get(cookies.NAMES.UUID);
if (cookie) {
return cookie;
}
const uuid = crypto.randomUUID();
cookies.set(cookies.NAMES.UUID, uuid);
if (isBrowser()) {
window.localStorage.removeItem(growthBook.STORAGE_KEY);
}
return uuid;
}
import getPageType from './getPageType'; import getPageType from './getPageType';
import getUuid from './getUuid';
import logEvent from './logEvent'; import logEvent from './logEvent';
import reset from './reset'; import reset from './reset';
import useInit from './useInit'; import useInit from './useInit';
...@@ -12,7 +11,6 @@ export { ...@@ -12,7 +11,6 @@ export {
useLogPageView, useLogPageView,
logEvent, logEvent,
getPageType, getPageType,
getUuid,
userProfile, userProfile,
reset, reset,
}; };
...@@ -10,7 +10,6 @@ import * as cookies from 'lib/cookies'; ...@@ -10,7 +10,6 @@ import * as cookies from 'lib/cookies';
import dayjs from 'lib/date/dayjs'; import dayjs from 'lib/date/dayjs';
import getQueryParamString from 'lib/router/getQueryParamString'; import getQueryParamString from 'lib/router/getQueryParamString';
import getUuid from './getUuid';
import * as userProfile from './userProfile'; import * as userProfile from './userProfile';
export default function useMixpanelInit() { export default function useMixpanelInit() {
...@@ -30,7 +29,8 @@ export default function useMixpanelInit() { ...@@ -30,7 +29,8 @@ export default function useMixpanelInit() {
debug: Boolean(debugFlagQuery.current || debugFlagCookie), debug: Boolean(debugFlagQuery.current || debugFlagCookie),
}; };
const isAuth = Boolean(cookies.get(cookies.NAMES.API_TOKEN)); const isAuth = Boolean(cookies.get(cookies.NAMES.API_TOKEN));
const userId = getUuid();
const uuid = cookies.get(cookies.NAMES.UUID);
mixpanel.init(feature.projectToken, mixpanelConfig); mixpanel.init(feature.projectToken, mixpanelConfig);
mixpanel.register({ mixpanel.register({
...@@ -41,9 +41,9 @@ export default function useMixpanelInit() { ...@@ -41,9 +41,9 @@ export default function useMixpanelInit() {
'Viewport height': window.innerHeight, 'Viewport height': window.innerHeight,
Language: window.navigator.language, Language: window.navigator.language,
'Device type': capitalize(deviceType), 'Device type': capitalize(deviceType),
'User id': userId, 'User id': uuid,
}); });
mixpanel.identify(userId); mixpanel.identify(uuid);
userProfile.set({ userProfile.set({
'Device Type': capitalize(deviceType), 'Device Type': capitalize(deviceType),
...(isAuth ? { 'With Account': true } : {}), ...(isAuth ? { 'With Account': true } : {}),
...@@ -56,7 +56,7 @@ export default function useMixpanelInit() { ...@@ -56,7 +56,7 @@ export default function useMixpanelInit() {
if (debugFlagQuery.current && !debugFlagCookie) { if (debugFlagQuery.current && !debugFlagCookie) {
cookies.set(cookies.NAMES.MIXPANEL_DEBUG, 'true'); cookies.set(cookies.NAMES.MIXPANEL_DEBUG, 'true');
} }
}, []); }, [ ]);
return isInited; return isInited;
} }
...@@ -3,6 +3,7 @@ export const URL_PREFIX = /^https?:\/\//i; ...@@ -3,6 +3,7 @@ export const URL_PREFIX = /^https?:\/\//i;
export const IPFS_PREFIX = /^ipfs:\/\//i; export const IPFS_PREFIX = /^ipfs:\/\//i;
export const HEX_REGEXP = /^(?:0x)?[\da-fA-F]+$/; export const HEX_REGEXP = /^(?:0x)?[\da-fA-F]+$/;
export const HEX_REGEXP_WITH_0X = /^0x[\da-fA-F]+$/;
export const FILE_EXTENSION = /\.([\da-z]+)$/i; export const FILE_EXTENSION = /\.([\da-z]+)$/i;
......
...@@ -6,7 +6,7 @@ import config from 'configs/app'; ...@@ -6,7 +6,7 @@ import config from 'configs/app';
import { ABSENT_PARAM_ERROR_MESSAGE } from 'lib/errors/throwOnAbsentParamError'; import { ABSENT_PARAM_ERROR_MESSAGE } from 'lib/errors/throwOnAbsentParamError';
import { RESOURCE_LOAD_ERROR_MESSAGE } from 'lib/errors/throwOnResourceLoadError'; import { RESOURCE_LOAD_ERROR_MESSAGE } from 'lib/errors/throwOnResourceLoadError';
import { isBot, isHeadlessBrowser, isNextJsChunkError, getRequestInfo } from './utils'; import { isBot, isHeadlessBrowser, isNextJsChunkError, getRequestInfo, getExceptionClass } from './utils';
const feature = config.features.rollbar; const feature = config.features.rollbar;
...@@ -37,16 +37,23 @@ export const clientConfig: Configuration | undefined = feature.isEnabled ? { ...@@ -37,16 +37,23 @@ export const clientConfig: Configuration | undefined = feature.isEnabled ? {
return true; return true;
} }
const exceptionClass = getExceptionClass(item);
const IGNORED_EXCEPTION_CLASSES = [
// these are React errors - "NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node."
// they could be caused by browser extensions
// one of the examples - https://github.com/facebook/react/issues/11538
// we can ignore them for now
'NotFoundError',
];
if (exceptionClass && IGNORED_EXCEPTION_CLASSES.includes(exceptionClass)) {
return true;
}
return false; return false;
}, },
hostSafeList: [ config.app.host ].filter(Boolean), hostSafeList: [ config.app.host ].filter(Boolean),
ignoredMessages: [ ignoredMessages: [
// these are React errors - "NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node."
// they could be caused by browser extensions
// one of the examples - https://github.com/facebook/react/issues/11538
// we can ignore them for now
'NotFoundError',
// these are errors that we throw on when make a call to the API // these are errors that we throw on when make a call to the API
RESOURCE_LOAD_ERROR_MESSAGE, RESOURCE_LOAD_ERROR_MESSAGE,
ABSENT_PARAM_ERROR_MESSAGE, ABSENT_PARAM_ERROR_MESSAGE,
......
import { get } from 'es-toolkit/compat';
import type { Dictionary } from 'rollbar'; import type { Dictionary } from 'rollbar';
export function isBot(userAgent: string | undefined) { export function isBot(userAgent: string | undefined) {
...@@ -56,3 +57,9 @@ export function getRequestInfo(item: Dictionary): { url: string } | undefined { ...@@ -56,3 +57,9 @@ export function getRequestInfo(item: Dictionary): { url: string } | undefined {
} }
return { url: item.request.url }; return { url: item.request.url };
} }
export function getExceptionClass(item: Dictionary) {
const exceptionClass = get(item, 'body.trace.exception.class');
return typeof exceptionClass === 'string' ? exceptionClass : undefined;
}
...@@ -10,11 +10,13 @@ type Args = { ...@@ -10,11 +10,13 @@ type Args = {
confirmation_transaction: ArbitrumL2TxData; confirmation_transaction: ArbitrumL2TxData;
}; };
const parentChainName = rollupFeature.isEnabled ? rollupFeature.parentChain.name : undefined;
export const VERIFICATION_STEPS_MAP: Record<ArbitrumBatchStatus, string> = { export const VERIFICATION_STEPS_MAP: Record<ArbitrumBatchStatus, string> = {
'Processed on rollup': 'Processed on rollup', 'Processed on rollup': 'Processed on rollup',
'Sent to base': rollupFeature.isEnabled && rollupFeature.parentChainName ? `Sent to ${ rollupFeature.parentChainName }` : 'Sent to parent chain', 'Sent to base': parentChainName ? `Sent to ${ parentChainName }` : 'Sent to parent chain',
'Confirmed on base': rollupFeature.isEnabled && rollupFeature.parentChainName ? 'Confirmed on base': parentChainName ?
`Confirmed on ${ rollupFeature.parentChainName }` : `Confirmed on ${ parentChainName }` :
'Confirmed on parent chain', 'Confirmed on parent chain',
}; };
......
/* eslint-disable max-len */
import type { ArbitrumMessageStatus } from 'types/api/transaction';
export const MESSAGE_DESCRIPTIONS: Record<ArbitrumMessageStatus, string> = {
'Syncing with base layer': 'The incoming message was discovered on the rollup, but the corresponding message on L1 has not yet been found',
'Settlement pending': 'The transaction with the message was included in a rollup block, but there is no batch on L1 containing the block yet',
'Waiting for confirmation': 'The rollup block with the transaction containing the message was included in a batch on L1, but it is still waiting for the expiration of the fraud proof countdown',
'Ready for relay': 'The rollup state was confirmed successfully, and the message can be executed—funds can be claimed on L1',
Relayed: '',
};
...@@ -2,7 +2,7 @@ import { type Chain } from 'viem'; ...@@ -2,7 +2,7 @@ import { type Chain } from 'viem';
import config from 'configs/app'; import config from 'configs/app';
const currentChain = { export const currentChain: Chain = {
id: Number(config.chain.id), id: Number(config.chain.id),
name: config.chain.name ?? '', name: config.chain.name ?? '',
nativeCurrency: { nativeCurrency: {
...@@ -22,6 +22,36 @@ const currentChain = { ...@@ -22,6 +22,36 @@ const currentChain = {
}, },
}, },
testnet: config.chain.isTestnet, testnet: config.chain.isTestnet,
} as const satisfies Chain; };
export default currentChain; export const parentChain: Chain | undefined = (() => {
const rollupFeature = config.features.rollup;
const parentChain = rollupFeature.isEnabled && rollupFeature.parentChain;
if (!parentChain) {
return;
}
if (!parentChain.id || !parentChain.name || !parentChain.rpcUrls || !parentChain.baseUrl || !parentChain.currency) {
return;
}
return {
id: parentChain.id,
name: parentChain.name,
nativeCurrency: parentChain.currency,
rpcUrls: {
'default': {
http: parentChain.rpcUrls,
},
},
blockExplorers: {
'default': {
name: 'Blockscout',
url: parentChain.baseUrl,
},
},
testnet: parentChain.isTestnet,
};
})();
import { createPublicClient, http } from 'viem'; import { createPublicClient, http } from 'viem';
import currentChain from './currentChain'; import { currentChain } from './chains';
export const publicClient = (() => { export const publicClient = (() => {
if (currentChain.rpcUrls.default.http.filter(Boolean).length === 0) { if (currentChain.rpcUrls.default.http.filter(Boolean).length === 0) {
......
...@@ -7,9 +7,10 @@ import useAccount from 'lib/web3/useAccount'; ...@@ -7,9 +7,10 @@ import useAccount from 'lib/web3/useAccount';
interface Params { interface Params {
source: mixpanel.EventPayload<mixpanel.EventTypes.WALLET_CONNECT>['Source']; source: mixpanel.EventPayload<mixpanel.EventTypes.WALLET_CONNECT>['Source'];
onConnect?: () => void;
} }
export default function useWeb3Wallet({ source }: Params) { export default function useWeb3Wallet({ source, onConnect }: Params) {
const { open: openModal } = useAppKit(); const { open: openModal } = useAppKit();
const { open: isOpen } = useAppKitState(); const { open: isOpen } = useAppKitState();
const { disconnect } = useDisconnect(); const { disconnect } = useDisconnect();
...@@ -35,9 +36,10 @@ export default function useWeb3Wallet({ source }: Params) { ...@@ -35,9 +36,10 @@ export default function useWeb3Wallet({ source }: Params) {
mixpanel.userProfile.setOnce({ mixpanel.userProfile.setOnce({
'With Connected Wallet': true, 'With Connected Wallet': true,
}); });
onConnect?.();
} }
isConnectionStarted.current = false; isConnectionStarted.current = false;
}, [ source ]); }, [ source, onConnect ]);
const handleDisconnect = React.useCallback(() => { const handleDisconnect = React.useCallback(() => {
disconnect(); disconnect();
......
import { WagmiAdapter } from '@reown/appkit-adapter-wagmi'; import { WagmiAdapter } from '@reown/appkit-adapter-wagmi';
import type { AppKitNetwork } from '@reown/appkit/networks';
import type { Chain } from 'viem';
import { fallback, http } from 'viem'; import { fallback, http } from 'viem';
import { createConfig } from 'wagmi'; import { createConfig } from 'wagmi';
import config from 'configs/app'; import config from 'configs/app';
import currentChain from 'lib/web3/currentChain'; import { currentChain, parentChain } from 'lib/web3/chains';
const feature = config.features.blockchainInteraction; const feature = config.features.blockchainInteraction;
const chains = [ currentChain, parentChain ].filter(Boolean);
const wagmi = (() => { const wagmi = (() => {
const chains = [ currentChain ];
if (!feature.isEnabled) { if (!feature.isEnabled) {
const wagmiConfig = createConfig({ const wagmiConfig = createConfig({
chains: [ currentChain ], chains: chains as [Chain, ...Array<Chain>],
transports: { transports: {
[currentChain.id]: fallback( [currentChain.id]: fallback(
config.chain.rpcUrls config.chain.rpcUrls
.map((url) => http(url)) .map((url) => http(url))
.concat(http(`${ config.api.endpoint }/api/eth-rpc`)), .concat(http(`${ config.api.endpoint }/api/eth-rpc`)),
), ),
...(parentChain ? { [parentChain.id]: http(parentChain.rpcUrls.default.http[0]) } : {}),
}, },
ssr: true, ssr: true,
batch: { multicall: { wait: 100 } }, batch: { multicall: { wait: 100 } },
...@@ -27,10 +32,11 @@ const wagmi = (() => { ...@@ -27,10 +32,11 @@ const wagmi = (() => {
} }
const wagmiAdapter = new WagmiAdapter({ const wagmiAdapter = new WagmiAdapter({
networks: chains, networks: chains as Array<AppKitNetwork>,
multiInjectedProviderDiscovery: true, multiInjectedProviderDiscovery: true,
transports: { transports: {
[currentChain.id]: fallback(config.chain.rpcUrls.map((url) => http(url))), [currentChain.id]: fallback(config.chain.rpcUrls.map((url) => http(url))),
...(parentChain ? { [parentChain.id]: http() } : {}),
}, },
projectId: feature.walletConnect.projectId, projectId: feature.walletConnect.projectId,
ssr: true, ssr: true,
......
...@@ -23,6 +23,7 @@ export function middleware(req: NextRequest) { ...@@ -23,6 +23,7 @@ export function middleware(req: NextRequest) {
middlewares.colorTheme(req, res); middlewares.colorTheme(req, res);
middlewares.addressFormat(req, res); middlewares.addressFormat(req, res);
middlewares.scamTokens(req, res);
const end = Date.now(); const end = Date.now();
......
...@@ -60,6 +60,12 @@ export const withoutName: AddressParam = { ...@@ -60,6 +60,12 @@ export const withoutName: AddressParam = {
ens_domain_name: null, ens_domain_name: null,
}; };
export const delegated: AddressParam = {
...withoutName,
is_verified: true,
proxy_type: 'eip7702',
};
export const token: Address = { export const token: Address = {
hash: hash, hash: hash,
implementations: null, implementations: null,
......
...@@ -38,3 +38,16 @@ export const batchDataAnytrust: ArbitrumL2TxnBatch = { ...@@ -38,3 +38,16 @@ export const batchDataAnytrust: ArbitrumL2TxnBatch = {
], ],
}, },
}; };
export const batchDataCelestia: ArbitrumL2TxnBatch = {
...finalized,
after_acc: '0xcd064f3409015e8e6407e492e5275a185e492c6b43ccf127f22092d8057a9ffb',
before_acc: '0x2ed7c4985eb778d76ec400a43805e7feecc8c2afcdb492dbe5caf227de6d37bc',
start_block: 1245209,
end_block: 1245490,
data_availability: {
batch_data_container: 'in_celestia',
height: 4520041,
transaction_commitment: '0x3ebe5a43f47fbf69db003e543bb27e4875929ede2fa9a25d09f0bd082d5d20f0',
},
};
import type { ArbitrumL2TxnWithdrawalsItem } from 'types/api/arbitrumL2';
export const unclaimed: ArbitrumL2TxnWithdrawalsItem = {
arb_block_number: 115114348,
caller: '0x07e1e36fe70cd58a05c00812d573dc39a127ee6d',
callvalue: '21000000000000000000',
completion_transaction_hash: null,
data: '0x',
destination: '0x07e1e36fe70cd58a05c00812d573dc39a127ee6d',
eth_block_number: 7503173,
id: 59874,
l2_timestamp: 1737020350,
status: 'confirmed',
token: null,
};
export const claimed: ArbitrumL2TxnWithdrawalsItem = {
arb_block_number: 115114348,
caller: '0x07e1e36fe70cd58a05c00812d573dc39a127ee6d',
callvalue: '21000000000000000000',
completion_transaction_hash: '0x215382498438cb6532a5e5fb07d664bbf912187866591470d47c3cfbce2dc4a8',
data: '0x',
destination: '0x07e1e36fe70cd58a05c00812d573dc39a127ee6d',
eth_block_number: 7503173,
id: 59875,
l2_timestamp: 1737020350,
status: 'relayed',
token: {
address: '0x0000000000000000000000000000000000000000',
symbol: 'USDC',
name: 'USDC Token',
decimals: 6,
amount: '10000000000',
destination: '0x07e1e36fe70cd58a05c00812d573dc39a127ee6d',
},
};
...@@ -9,8 +9,10 @@ export const base: Pool = { ...@@ -9,8 +9,10 @@ export const base: Pool = {
quote_token_address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', quote_token_address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
quote_token_symbol: 'WETH', quote_token_symbol: 'WETH',
quote_token_icon_url: 'https://localhost:3000/secondary_utia.jpg', quote_token_icon_url: 'https://localhost:3000/secondary_utia.jpg',
fully_diluted_valuation_usd: '75486579078', base_token_fully_diluted_valuation_usd: '75486579078',
market_cap_usd: '139312819076.195', base_token_market_cap_usd: '139312819076.195',
quote_token_fully_diluted_valuation_usd: '486579078',
quote_token_market_cap_usd: '312819076.195',
liquidity: '2099941.2238', liquidity: '2099941.2238',
dex: { id: 'sushiswap', name: 'SushiSwap' }, dex: { id: 'sushiswap', name: 'SushiSwap' },
fee: '0.03', fee: '0.03',
......
...@@ -7,4 +7,7 @@ export const base: RewardsConfigResponse = { ...@@ -7,4 +7,7 @@ export const base: RewardsConfigResponse = {
daily_claim: '10', daily_claim: '10',
referral_share: '0.1', referral_share: '0.1',
}, },
auth: {
shared_siwe_login: true,
},
}; };
...@@ -8,6 +8,7 @@ import type { ...@@ -8,6 +8,7 @@ import type {
SearchResultUserOp, SearchResultUserOp,
SearchResultBlob, SearchResultBlob,
SearchResultDomain, SearchResultDomain,
SearchResultMetadataTag,
} from 'types/api/search'; } from 'types/api/search';
export const token1: SearchResultToken = { export const token1: SearchResultToken = {
...@@ -147,6 +148,42 @@ export const domain1: SearchResultDomain = { ...@@ -147,6 +148,42 @@ export const domain1: SearchResultDomain = {
url: '/address/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', url: '/address/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
}; };
export const metatag1: SearchResultMetadataTag = {
...address1,
type: 'metadata_tag',
metadata: {
name: 'utko',
slug: 'utko',
meta: {},
tagType: 'name',
ordinal: 1,
},
};
export const metatag2: SearchResultMetadataTag = {
...address2,
type: 'metadata_tag',
metadata: {
name: 'utko',
slug: 'utko',
meta: {},
tagType: 'name',
ordinal: 1,
},
};
export const metatag3: SearchResultMetadataTag = {
...contract2,
type: 'metadata_tag',
metadata: {
name: 'super utko',
slug: 'super-utko',
meta: {},
tagType: 'protocol',
ordinal: 1,
},
};
export const baseResponse: SearchResult = { export const baseResponse: SearchResult = {
items: [ items: [
token1, token1,
...@@ -157,6 +194,8 @@ export const baseResponse: SearchResult = { ...@@ -157,6 +194,8 @@ export const baseResponse: SearchResult = {
tx1, tx1,
blob1, blob1,
domain1, domain1,
metatag1,
], ],
next_page_params: null, next_page_params: null,
}; };
import type * as stats from '@blockscout/stats-types';
import { averageGasPrice } from './line';
export const base: stats.MainPageStats = {
average_block_time: {
id: 'averageBlockTime',
value: '14.909090909090908',
title: 'Average block time',
units: 's',
description: 'Average time taken in seconds for a block to be included in the blockchain',
},
total_addresses: {
id: 'totalAddresses',
value: '113606435',
title: 'Total addresses',
description: 'Number of addresses that participated in the blockchain',
},
total_blocks: {
id: 'totalBlocks',
value: '7660515',
title: 'Total blocks',
description: 'Number of blocks over all time',
},
total_transactions: {
id: 'totalTxns',
value: '411264599',
title: 'Total txns',
description: 'All transactions including pending, dropped, replaced, failed transactions',
},
yesterday_transactions: {
id: 'yesterdayTxns',
value: '213019',
title: 'Yesterday txns',
description: 'Number of transactions yesterday (0:00 - 23:59 UTC)',
},
total_operational_transactions: {
id: 'totalOperationalTxns',
value: '403598877',
title: 'Total operational txns',
description: '\'Total txns\' without block creation transactions',
},
yesterday_operational_transactions: {
id: 'yesterdayOperationalTxns',
value: '210852',
title: 'Yesterday operational txns',
description: 'Number of transactions yesterday (0:00 - 23:59 UTC) without block creation transactions',
},
daily_new_transactions: {
chart: averageGasPrice.chart,
info: {
id: 'newTxnsWindow',
title: 'Daily transactions',
description: 'The chart displays daily transactions for the past 30 days',
resolutions: [
'DAY',
],
},
},
daily_new_operational_transactions: {
chart: averageGasPrice.chart,
info: {
id: 'newOperationalTxnsWindow',
title: 'Daily operational transactions',
description: 'The chart displays daily transactions for the past 30 days (without block creation transactions)',
resolutions: [
'DAY',
],
},
},
};
...@@ -60,7 +60,7 @@ export const base: Transaction = { ...@@ -60,7 +60,7 @@ export const base: Transaction = {
}, },
token_transfers: [], token_transfers: [],
token_transfers_overflow: false, token_transfers_overflow: false,
tx_burnt_fee: '461030000000000', transaction_burnt_fee: '461030000000000',
transaction_tag: null, transaction_tag: null,
transaction_types: [ transaction_types: [
'contract_call', 'contract_call',
...@@ -196,7 +196,7 @@ export const pending: Transaction = { ...@@ -196,7 +196,7 @@ export const pending: Transaction = {
revert_reason: null, revert_reason: null,
status: null, status: null,
timestamp: null, timestamp: null,
tx_burnt_fee: null, transaction_burnt_fee: null,
transaction_tag: null, transaction_tag: null,
type: null, type: null,
value: '0', value: '0',
......
...@@ -66,6 +66,14 @@ export const userOpData: UserOp = { ...@@ -66,6 +66,14 @@ export const userOpData: UserOp = {
}, },
call_data: '0xb61d27f600000000000000000000000059f6aa952df7f048fd076e33e0ea8bb552d5ffd8000000000000000000000000000000000000000000000000003f3d017500800000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000', call_data: '0xb61d27f600000000000000000000000059f6aa952df7f048fd076e33e0ea8bb552d5ffd8000000000000000000000000000000000000000000000000003f3d017500800000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000',
execute_call_data: '0x3cf80e6c', execute_call_data: '0x3cf80e6c',
execute_target: {
ens_domain_name: null,
hash: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
implementations: null,
is_contract: true,
is_verified: true,
name: 'FiatTokenProxy',
},
decoded_call_data: { decoded_call_data: {
method_call: 'execute(address dest, uint256 value, bytes func)', method_call: 'execute(address dest, uint256 value, bytes func)',
method_id: 'b61d27f6', method_id: 'b61d27f6',
......
import type { ValidatorZilliqa, ValidatorsZilliqaItem, ValidatorsZilliqaResponse } from 'types/api/validators';
export const validator1: ValidatorsZilliqaItem = {
index: 420,
bls_public_key: '0x95125dca41be848801f9bd75254f1faf1ae3194b1da53e9a5684ed7f67b729542482bc521924603b9703c33bf831a100',
balance: '1000000000000000000',
};
export const validatorsResponse: ValidatorsZilliqaResponse = {
items: [ validator1 ],
next_page_params: null,
};
export const validatorDetails: ValidatorZilliqa = {
added_at_block_number: 7527600,
balance: '20000000000000000000000000',
bls_public_key: '0x95125dca41be848801f9bd75254f1faf1ae3194b1da53e9a5684ed7f67b729542482bc521924603b9703c33bf831a100',
control_address: {
ens_domain_name: null,
hash: '0xB4492C468Fe97CB73Ea70a9A712cdd5B5aB621c3',
implementations: [],
is_contract: false,
is_verified: null,
metadata: null,
name: null,
private_tags: [],
proxy_type: null,
public_tags: [],
watchlist_names: [],
},
index: 1,
peer_id: '0x002408011220a8ce8c9a146f3dc411cd72ba845b76722824c55824ac74b3362f070a332d85f2',
reward_address: {
ens_domain_name: null,
hash: '0x0000000000000000000000000000000000000000',
implementations: [],
is_contract: false,
is_verified: null,
metadata: null,
name: null,
private_tags: [],
proxy_type: null,
public_tags: [],
watchlist_names: [],
},
signing_address: {
ens_domain_name: null,
hash: '0x0000000000000000000000000000000000000026',
implementations: [],
is_contract: false,
is_verified: null,
metadata: null,
name: null,
private_tags: [],
proxy_type: null,
public_tags: [],
watchlist_names: [],
},
stake_updated_at_block_number: 7527642,
};
...@@ -52,6 +52,7 @@ export function app(): CspDev.DirectiveDescriptor { ...@@ -52,6 +52,7 @@ export function app(): CspDev.DirectiveDescriptor {
// chain RPC server // chain RPC server
...config.chain.rpcUrls, ...config.chain.rpcUrls,
...(getFeaturePayload(config.features.rollup)?.parentChain?.rpcUrls ?? []),
'https://infragrid.v.network', // RPC providers 'https://infragrid.v.network', // RPC providers
// github (spec for api-docs page) // github (spec for api-docs page)
......
...@@ -8,6 +8,9 @@ export function googleReCaptcha(): CspDev.DirectiveDescriptor { ...@@ -8,6 +8,9 @@ export function googleReCaptcha(): CspDev.DirectiveDescriptor {
} }
return { return {
'connect-src': [
'https://www.google.com/recaptcha/api2/clr',
],
'script-src': [ 'script-src': [
'https://www.google.com/recaptcha/api.js', 'https://www.google.com/recaptcha/api.js',
'https://www.gstatic.com', 'https://www.gstatic.com',
......
...@@ -9,6 +9,7 @@ import config from 'configs/app'; ...@@ -9,6 +9,7 @@ import config from 'configs/app';
const rollupFeature = config.features.rollup; const rollupFeature = config.features.rollup;
const adBannerFeature = config.features.adsBanner; const adBannerFeature = config.features.adsBanner;
import isNeedProxy from 'lib/api/isNeedProxy'; import isNeedProxy from 'lib/api/isNeedProxy';
import * as cookies from 'lib/cookies';
import type * as metadata from 'lib/metadata'; import type * as metadata from 'lib/metadata';
export interface Props<Pathname extends Route['pathname'] = never> { export interface Props<Pathname extends Route['pathname'] = never> {
...@@ -19,9 +20,10 @@ export interface Props<Pathname extends Route['pathname'] = never> { ...@@ -19,9 +20,10 @@ export interface Props<Pathname extends Route['pathname'] = never> {
// if apiData is undefined, Next.js will complain that it is not serializable // if apiData is undefined, Next.js will complain that it is not serializable
// so we force it to be always present in the props but it can be null // so we force it to be always present in the props but it can be null
apiData: metadata.ApiData<Pathname> | null; apiData: metadata.ApiData<Pathname> | null;
uuid: string;
} }
export const base = async <Pathname extends Route['pathname'] = never>({ req, query }: GetServerSidePropsContext): export const base = async <Pathname extends Route['pathname'] = never>({ req, res, query }: GetServerSidePropsContext):
Promise<GetServerSidePropsResult<Props<Pathname>>> => { Promise<GetServerSidePropsResult<Props<Pathname>>> => {
const adBannerProvider = (() => { const adBannerProvider = (() => {
if (adBannerFeature.isEnabled) { if (adBannerFeature.isEnabled) {
...@@ -36,6 +38,36 @@ Promise<GetServerSidePropsResult<Props<Pathname>>> => { ...@@ -36,6 +38,36 @@ Promise<GetServerSidePropsResult<Props<Pathname>>> => {
return null; return null;
})(); })();
let uuid = cookies.getFromCookieString(req.headers.cookie || '', cookies.NAMES.UUID);
if (!uuid) {
uuid = crypto.randomUUID();
res.setHeader('Set-Cookie', `${ cookies.NAMES.UUID }=${ uuid }`);
}
const isTrackingDisabled = process.env.DISABLE_TRACKING === 'true';
if (!isTrackingDisabled) {
// log pageview
const hostname = req.headers.host;
const timestamp = new Date().toISOString();
const chainId = process.env.NEXT_PUBLIC_NETWORK_ID;
const chainName = process.env.NEXT_PUBLIC_NETWORK_NAME;
const publicRPC = process.env.NEXT_PUBLIC_NETWORK_RPC_URL;
fetch('https://monitor.blockscout.com/count', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
hostname,
timestamp,
chainId,
chainName,
publicRPC,
uuid,
}),
});
}
return { return {
props: { props: {
query, query,
...@@ -43,6 +75,7 @@ Promise<GetServerSidePropsResult<Props<Pathname>>> => { ...@@ -43,6 +75,7 @@ Promise<GetServerSidePropsResult<Props<Pathname>>> => {
referrer: req.headers.referer || '', referrer: req.headers.referer || '',
adBannerProvider: adBannerProvider, adBannerProvider: adBannerProvider,
apiData: null, apiData: null,
uuid,
}, },
}; };
}; };
...@@ -92,6 +125,16 @@ export const withdrawals: GetServerSideProps<Props> = async(context) => { ...@@ -92,6 +125,16 @@ export const withdrawals: GetServerSideProps<Props> = async(context) => {
return base(context); return base(context);
}; };
export const txnWithdrawals: GetServerSideProps<Props> = async(context) => {
if (!(rollupFeature.isEnabled && rollupFeature.type === 'arbitrum')) {
return {
notFound: true,
};
}
return base(context);
};
export const rollup: GetServerSideProps<Props> = async(context) => { export const rollup: GetServerSideProps<Props> = async(context) => {
if (!config.features.rollup.isEnabled) { if (!config.features.rollup.isEnabled) {
return { return {
...@@ -123,6 +166,16 @@ export const batch: GetServerSideProps<Props> = async(context) => { ...@@ -123,6 +166,16 @@ export const batch: GetServerSideProps<Props> = async(context) => {
return base(context); return base(context);
}; };
export const batchCelestia: GetServerSideProps<Props> = async(context) => {
if (!(rollupFeature.isEnabled && (rollupFeature.type === 'arbitrum' || rollupFeature.type === 'optimistic'))) {
return {
notFound: true,
};
}
return base(context);
};
export const marketplace = async <Pathname extends Route['pathname'] = never>(context: GetServerSidePropsContext): export const marketplace = async <Pathname extends Route['pathname'] = never>(context: GetServerSidePropsContext):
Promise<GetServerSidePropsResult<Props<Pathname>>> => { Promise<GetServerSidePropsResult<Props<Pathname>>> => {
if (!config.features.marketplace.isEnabled) { if (!config.features.marketplace.isEnabled) {
...@@ -234,6 +287,17 @@ export const validators: GetServerSideProps<Props> = async(context) => { ...@@ -234,6 +287,17 @@ export const validators: GetServerSideProps<Props> = async(context) => {
return base(context); return base(context);
}; };
export const validatorDetails: GetServerSideProps<Props> = async(context) => {
const feature = config.features.validators;
if (!feature.isEnabled || feature.chainType !== 'zilliqa') {
return {
notFound: true,
};
}
return base(context);
};
export const gasTracker: GetServerSideProps<Props> = async(context) => { export const gasTracker: GetServerSideProps<Props> = async(context) => {
if (!config.features.gasTracker.isEnabled) { if (!config.features.gasTracker.isEnabled) {
return { return {
......
export { account } from './account'; export { account } from './account';
export { default as colorTheme } from './colorTheme'; export { default as colorTheme } from './colorTheme';
export { default as addressFormat } from './addressFormat'; export { default as addressFormat } from './addressFormat';
export { default as scamTokens } from './scamTokens';
import type { NextRequest, NextResponse } from 'next/server';
import config from 'configs/app';
import * as cookiesLib from 'lib/cookies';
export default function scamTokensMiddleware(req: NextRequest, res: NextResponse) {
if (config.UI.views.token.hideScamTokensEnabled) {
const showScamTokensCookie = req.cookies.get(cookiesLib.NAMES.SHOW_SCAM_TOKENS);
if (!showScamTokensCookie) {
res.cookies.set(cookiesLib.NAMES.SHOW_SCAM_TOKENS, 'false', { path: '/' });
}
}
}
...@@ -9,7 +9,7 @@ declare module "nextjs-routes" { ...@@ -9,7 +9,7 @@ declare module "nextjs-routes" {
| StaticRoute<"/404"> | StaticRoute<"/404">
| StaticRoute<"/account/api-key"> | StaticRoute<"/account/api-key">
| StaticRoute<"/account/custom-abi"> | StaticRoute<"/account/custom-abi">
| StaticRoute<"/account/rewards"> | StaticRoute<"/account/merits">
| StaticRoute<"/account/tag-address"> | StaticRoute<"/account/tag-address">
| StaticRoute<"/account/verified-addresses"> | StaticRoute<"/account/verified-addresses">
| StaticRoute<"/account/watchlist"> | StaticRoute<"/account/watchlist">
...@@ -32,6 +32,7 @@ declare module "nextjs-routes" { ...@@ -32,6 +32,7 @@ declare module "nextjs-routes" {
| StaticRoute<"/apps"> | StaticRoute<"/apps">
| StaticRoute<"/auth/profile"> | StaticRoute<"/auth/profile">
| DynamicRoute<"/batches/[number]", { "number": string }> | DynamicRoute<"/batches/[number]", { "number": string }>
| DynamicRoute<"/batches/celestia/[height]/[commitment]", { "height": string; "commitment": string }>
| StaticRoute<"/batches"> | StaticRoute<"/batches">
| DynamicRoute<"/blobs/[hash]", { "hash": string }> | DynamicRoute<"/blobs/[hash]", { "hash": string }>
| DynamicRoute<"/block/[height_or_hash]", { "height_or_hash": string }> | DynamicRoute<"/block/[height_or_hash]", { "height_or_hash": string }>
...@@ -46,6 +47,7 @@ declare module "nextjs-routes" { ...@@ -46,6 +47,7 @@ declare module "nextjs-routes" {
| StaticRoute<"/gas-tracker"> | StaticRoute<"/gas-tracker">
| StaticRoute<"/graphiql"> | StaticRoute<"/graphiql">
| StaticRoute<"/"> | StaticRoute<"/">
| StaticRoute<"/internal-txs">
| StaticRoute<"/login"> | StaticRoute<"/login">
| StaticRoute<"/mud-worlds"> | StaticRoute<"/mud-worlds">
| DynamicRoute<"/name-domains/[name]", { "name": string }> | DynamicRoute<"/name-domains/[name]", { "name": string }>
...@@ -65,8 +67,10 @@ declare module "nextjs-routes" { ...@@ -65,8 +67,10 @@ declare module "nextjs-routes" {
| StaticRoute<"/token-transfers"> | StaticRoute<"/token-transfers">
| StaticRoute<"/tokens"> | StaticRoute<"/tokens">
| DynamicRoute<"/tx/[hash]", { "hash": string }> | DynamicRoute<"/tx/[hash]", { "hash": string }>
| StaticRoute<"/txn-withdrawals">
| StaticRoute<"/txs"> | StaticRoute<"/txs">
| DynamicRoute<"/txs/kettle/[hash]", { "hash": string }> | DynamicRoute<"/txs/kettle/[hash]", { "hash": string }>
| DynamicRoute<"/validators/[id]", { "id": string }>
| StaticRoute<"/validators"> | StaticRoute<"/validators">
| StaticRoute<"/verified-contracts"> | StaticRoute<"/verified-contracts">
| StaticRoute<"/visualize/sol2uml"> | StaticRoute<"/visualize/sol2uml">
......
...@@ -52,6 +52,10 @@ const oldUrls = [ ...@@ -52,6 +52,10 @@ const oldUrls = [
source: '/account/public-tags-request', source: '/account/public-tags-request',
destination: '/public-tags/submit', destination: '/public-tags/submit',
}, },
{
source: '/account/rewards',
destination: '/account/merits',
},
// TRANSACTIONS // TRANSACTIONS
{ {
......
...@@ -7,20 +7,20 @@ import nodeFetch from 'node-fetch'; ...@@ -7,20 +7,20 @@ import nodeFetch from 'node-fetch';
import { httpLogger } from 'nextjs/utils/logger'; import { httpLogger } from 'nextjs/utils/logger';
import * as cookies from 'lib/cookies';
export default function fetchFactory( export default function fetchFactory(
_req: NextApiRequest | (IncomingMessage & { cookies: NextApiRequestCookies }), _req: NextApiRequest | (IncomingMessage & { cookies: NextApiRequestCookies }),
) { ) {
// first arg can be only a string // first arg can be only a string
// FIXME migrate to RequestInfo later if needed // FIXME migrate to RequestInfo later if needed
return function fetch(url: string, init?: RequestInit): Promise<Response> { return function fetch(url: string, init?: RequestInit): Promise<Response> {
const apiToken = _req.cookies[cookies.NAMES.API_TOKEN]; const cookie = Object.entries(_req.cookies)
.map(([ key, value ]) => `${ key }=${ value }`)
.join('; ');
const headers = { const headers = {
accept: _req.headers['accept'] || 'application/json', accept: _req.headers['accept'] || 'application/json',
'content-type': _req.headers['content-type'] || 'application/json', 'content-type': _req.headers['content-type'] || 'application/json',
cookie: apiToken ? `${ cookies.NAMES.API_TOKEN }=${ apiToken }` : '', cookie,
...pick(_req.headers, [ ...pick(_req.headers, [
'x-csrf-token', 'x-csrf-token',
'Authorization', // the old value, just in case 'Authorization', // the old value, just in case
......
...@@ -14,7 +14,7 @@ import { MarketplaceContextProvider } from 'lib/contexts/marketplace'; ...@@ -14,7 +14,7 @@ import { MarketplaceContextProvider } from 'lib/contexts/marketplace';
import { RewardsContextProvider } from 'lib/contexts/rewards'; import { RewardsContextProvider } from 'lib/contexts/rewards';
import { ScrollDirectionProvider } from 'lib/contexts/scrollDirection'; import { ScrollDirectionProvider } from 'lib/contexts/scrollDirection';
import { SettingsContextProvider } from 'lib/contexts/settings'; import { SettingsContextProvider } from 'lib/contexts/settings';
import { growthBook } from 'lib/growthbook/init'; import { initGrowthBook } from 'lib/growthbook/init';
import useLoadFeatures from 'lib/growthbook/useLoadFeatures'; import useLoadFeatures from 'lib/growthbook/useLoadFeatures';
import useNotifyOnNavigation from 'lib/hooks/useNotifyOnNavigation'; import useNotifyOnNavigation from 'lib/hooks/useNotifyOnNavigation';
import { clientConfig as rollbarConfig, Provider as RollbarProvider } from 'lib/rollbar'; import { clientConfig as rollbarConfig, Provider as RollbarProvider } from 'lib/rollbar';
...@@ -56,10 +56,11 @@ function MyApp({ Component, pageProps }: AppPropsWithLayout) { ...@@ -56,10 +56,11 @@ function MyApp({ Component, pageProps }: AppPropsWithLayout) {
React.useEffect(() => { React.useEffect(() => {
setMounted(true); setMounted(true);
}, []); }, []);
useLoadFeatures(); useLoadFeatures(pageProps.uuid);
useNotifyOnNavigation(); useNotifyOnNavigation();
const growthBook = initGrowthBook(pageProps.uuid);
const queryClient = useQueryClientConfig(); const queryClient = useQueryClientConfig();
if (!mounted) { if (!mounted) {
......
...@@ -4,12 +4,12 @@ import React from 'react'; ...@@ -4,12 +4,12 @@ import React from 'react';
import PageNextJs from 'nextjs/PageNextJs'; import PageNextJs from 'nextjs/PageNextJs';
// const RewardsDashboard = dynamic(() => import('ui/pages/RewardsDashboard'), { ssr: false }); const RewardsDashboard = dynamic(() => import('ui/pages/RewardsDashboard'), { ssr: false });
const Page: NextPage = () => { const Page: NextPage = () => {
return ( return (
<PageNextJs pathname="/account/rewards"> <PageNextJs pathname="/account/merits">
{ /* <RewardsDashboard/> */ } <RewardsDashboard/>
</PageNextJs> </PageNextJs>
); );
}; };
......
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import React from 'react';
import type { Props } from 'nextjs/getServerSideProps';
import PageNextJs from 'nextjs/PageNextJs';
import config from 'configs/app';
const rollupFeature = config.features.rollup;
const Batch = dynamic(() => {
if (!rollupFeature.isEnabled) {
throw new Error('Rollup feature is not enabled.');
}
switch (rollupFeature.type) {
case 'arbitrum':
return import('ui/pages/ArbitrumL2TxnBatch');
case 'optimistic':
return import('ui/pages/OptimisticL2TxnBatch');
}
throw new Error('Celestia txn batches feature is not enabled.');
}, { ssr: false });
const Page: NextPage<Props> = (props: Props) => {
return (
<PageNextJs pathname="/batches/celestia/[height]/[commitment]" query={ props.query }>
<Batch/>
</PageNextJs>
);
};
export default Page;
export { batchCelestia as getServerSideProps } from 'nextjs/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import React from 'react';
import PageNextJs from 'nextjs/PageNextJs';
const InternalTxs = dynamic(() => import('ui/pages/InternalTxs'), { ssr: false });
const Page: NextPage = () => {
return (
<PageNextJs pathname="/internal-txs">
<InternalTxs/>
</PageNextJs>
);
};
export default Page;
export { base as getServerSideProps } from 'nextjs/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import React from 'react';
import PageNextJs from 'nextjs/PageNextJs';
import config from 'configs/app';
const rollupFeature = config.features.rollup;
const Withdrawals = dynamic(() => {
if (rollupFeature.isEnabled && rollupFeature.type === 'arbitrum') {
return import('ui/pages/ArbitrumL2TxnWithdrawals');
}
throw new Error('Txn withdrawals feature is not enabled.');
}, { ssr: false });
const Page: NextPage = () => {
return (
<PageNextJs pathname="/txn-withdrawals">
<Withdrawals/>
</PageNextJs>
);
};
export default Page;
export { txnWithdrawals as getServerSideProps } from 'nextjs/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import React from 'react';
import type { Props } from 'nextjs/getServerSideProps';
import PageNextJs from 'nextjs/PageNextJs';
import config from 'configs/app';
const validatorsFeature = config.features.validators;
const ValidatorDetails = dynamic(() => {
if (validatorsFeature.isEnabled && validatorsFeature.chainType === 'zilliqa') {
return import('ui/pages/ValidatorZilliqa');
}
throw new Error('Validators feature is not enabled.');
}, { ssr: false });
const Page: NextPage<Props> = (props) => {
return (
<PageNextJs pathname="/validators/[id]" query={ props.query }>
<ValidatorDetails/>
</PageNextJs>
);
};
export default Page;
export { validatorDetails as getServerSideProps } from 'nextjs/getServerSideProps';
...@@ -8,22 +8,26 @@ import config from 'configs/app'; ...@@ -8,22 +8,26 @@ import config from 'configs/app';
const validatorsFeature = config.features.validators; const validatorsFeature = config.features.validators;
// const Validators = dynamic(() => { const Validators = dynamic(() => {
// if (validatorsFeature.isEnabled && validatorsFeature.chainType === 'stability') { if (validatorsFeature.isEnabled && validatorsFeature.chainType === 'stability') {
// return import('ui/pages/ValidatorsStability'); return import('ui/pages/ValidatorsStability');
// } }
// if (validatorsFeature.isEnabled && validatorsFeature.chainType === 'blackfort') { if (validatorsFeature.isEnabled && validatorsFeature.chainType === 'blackfort') {
// return import('ui/pages/ValidatorsBlackfort'); return import('ui/pages/ValidatorsBlackfort');
// } }
// throw new Error('Validators feature is not enabled.'); if (validatorsFeature.isEnabled && validatorsFeature.chainType === 'zilliqa') {
// }, { ssr: false }); return import('ui/pages/ValidatorsZilliqa');
}
throw new Error('Validators feature is not enabled.');
}, { ssr: false });
const Page: NextPage = () => { const Page: NextPage = () => {
return ( return (
<PageNextJs pathname="/validators"> <PageNextJs pathname="/validators">
{ /* <Validators/> */ } <Validators/>
</PageNextJs> </PageNextJs>
); );
}; };
......
...@@ -13,7 +13,7 @@ import { MarketplaceContext } from 'lib/contexts/marketplace'; ...@@ -13,7 +13,7 @@ import { MarketplaceContext } from 'lib/contexts/marketplace';
import { RewardsContextProvider } from 'lib/contexts/rewards'; import { RewardsContextProvider } from 'lib/contexts/rewards';
import { SettingsContextProvider } from 'lib/contexts/settings'; import { SettingsContextProvider } from 'lib/contexts/settings';
import { SocketProvider } from 'lib/socket/context'; import { SocketProvider } from 'lib/socket/context';
import currentChain from 'lib/web3/currentChain'; import { currentChain } from 'lib/web3/chains';
import { Provider as ChakraProvider } from 'toolkit/chakra/provider'; import { Provider as ChakraProvider } from 'toolkit/chakra/provider';
import { port as socketPort } from './utils/socket'; import { port as socketPort } from './utils/socket';
...@@ -38,6 +38,7 @@ const defaultAppContext = { ...@@ -38,6 +38,7 @@ const defaultAppContext = {
query: {}, query: {},
adBannerProvider: 'slise' as const, adBannerProvider: 'slise' as const,
apiData: null, apiData: null,
uuid: '123',
}, },
}; };
......
...@@ -26,6 +26,7 @@ export const ENVS_MAP: Record<string, Array<[string, string]>> = { ...@@ -26,6 +26,7 @@ export const ENVS_MAP: Record<string, Array<[string, string]>> = {
[ 'NEXT_PUBLIC_ROLLUP_TYPE', 'arbitrum' ], [ 'NEXT_PUBLIC_ROLLUP_TYPE', 'arbitrum' ],
[ 'NEXT_PUBLIC_ROLLUP_L1_BASE_URL', 'https://localhost:3101' ], [ 'NEXT_PUBLIC_ROLLUP_L1_BASE_URL', 'https://localhost:3101' ],
[ 'NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME', 'DuckChain' ], [ 'NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME', 'DuckChain' ],
[ 'NEXT_PUBLIC_ROLLUP_DA_CELESTIA_NAMESPACE', '0x1234' ],
], ],
shibariumRollup: [ shibariumRollup: [
[ 'NEXT_PUBLIC_ROLLUP_TYPE', 'shibarium' ], [ 'NEXT_PUBLIC_ROLLUP_TYPE', 'shibarium' ],
...@@ -93,4 +94,7 @@ export const ENVS_MAP: Record<string, Array<[string, string]>> = { ...@@ -93,4 +94,7 @@ export const ENVS_MAP: Record<string, Array<[string, string]>> = {
[ 'NEXT_PUBLIC_ADDRESS_FORMAT', '["bech32","base16"]' ], [ 'NEXT_PUBLIC_ADDRESS_FORMAT', '["bech32","base16"]' ],
[ 'NEXT_PUBLIC_VIEWS_ADDRESS_BECH_32_PREFIX', 'tom' ], [ 'NEXT_PUBLIC_VIEWS_ADDRESS_BECH_32_PREFIX', 'tom' ],
], ],
externalTxs: [
[ 'NEXT_PUBLIC_TX_EXTERNAL_TRANSACTIONS_CONFIG', '{"chain_name": "Solana", "chain_logo_url": "http://example.url", "explorer_url_template": "https://scan.io/tx/{hash}"}' ],
],
}; };
...@@ -84,6 +84,7 @@ ...@@ -84,6 +84,7 @@
| "info" | "info"
| "integration/full" | "integration/full"
| "integration/partial" | "integration/partial"
| "internal_txns"
| "key" | "key"
| "lightning_navbar" | "lightning_navbar"
| "lightning" | "lightning"
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
<path d="M223.424 78.967a11.355 11.355 0 0 0 .001 0h-.001Z" fill="url(#h)"/> <path d="M223.424 78.967a11.355 11.355 0 0 0 .001 0h-.001Z" fill="url(#h)"/>
<path d="M195.759 63.318c.861 1.087.532.618 1.771 1.334l20.691 11.96a11.175 11.175 0 0 0 11.19 0l1.637-.945c-.715-4.798-2.488-7.243-4.079-9.436-1.74-2.398-3.261-4.495-2.941-9.04.392-5.57-.354-8.481-.999-11.003-.239-.934-.465-1.815-.614-2.758-2.56-5.59-3.746-10.222-4.126-14.142L235.64 25.8l-17.402-1.72c.186-2.314.635-4.337 1.15-6.154l.022-.08-5.809 2.608-2.722 3.012-2.008 5.822-.903 6.423c-1.486 1.522-2.857 3.095-4.472 5.813l-1.935 2.687c-.129.218-1.214 2.407-2.301 4.603h-.001l-.001.004-.001.002c-1.095 2.21-2.192 4.426-2.318 4.636-.367.612-1.181 3.51-1.921 6.141v.001l-.001.004-.001.003c-.231.822.943 3.02.743 3.713Z" fill="url(#i)"/> <path d="M195.759 63.318c.861 1.087.532.618 1.771 1.334l20.691 11.96a11.175 11.175 0 0 0 11.19 0l1.637-.945c-.715-4.798-2.488-7.243-4.079-9.436-1.74-2.398-3.261-4.495-2.941-9.04.392-5.57-.354-8.481-.999-11.003-.239-.934-.465-1.815-.614-2.758-2.56-5.59-3.746-10.222-4.126-14.142L235.64 25.8l-17.402-1.72c.186-2.314.635-4.337 1.15-6.154l.022-.08-5.809 2.608-2.722 3.012-2.008 5.822-.903 6.423c-1.486 1.522-2.857 3.095-4.472 5.813l-1.935 2.687c-.129.218-1.214 2.407-2.301 4.603h-.001l-.001.004-.001.002c-1.095 2.21-2.192 4.426-2.318 4.636-.367.612-1.181 3.51-1.921 6.141v.001l-.001.004-.001.003c-.231.822.943 3.02.743 3.713Z" fill="url(#i)"/>
<path d="M214.861 30.622c1.5-3.43 5.354-3.49 8.579-3.646 3.225.156 7.081.06 8.58 3.646 1.305 3.123-.869 9.783-2.589 11.45-2.006 1.944-4.492 1.56-5.991 1.56-1.5 0-3.984.384-5.99-1.56-1.721-1.667-3.942-8.354-2.589-11.45Z" fill="#D47B3A"/> <path d="M214.861 30.622c1.5-3.43 5.354-3.49 8.579-3.646 3.225.156 7.081.06 8.58 3.646 1.305 3.123-.869 9.783-2.589 11.45-2.006 1.944-4.492 1.56-5.991 1.56-1.5 0-3.984.384-5.99-1.56-1.721-1.667-3.942-8.354-2.589-11.45Z" fill="#D47B3A"/>
<path d="M230.164 36.42s2.765 1.587 4.98.358m-5.152 1.342s2.218 1.831 4.084 1.55m-16.766-3.25s-2.765 1.587-4.98.358m5.154 1.342s-1.966 1.831-3.832 1.55m14.068-1.755c-.883 1.534-4.037 1.943-4.037-1.125v-1.739M219.645 37.915c.883 1.534 4.038 1.943 4.038-1.125v-1.739" stroke="#562E11" stroke-width=".645" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> <path d="M230.164 36.42s2.765 1.587 4.98.358m-5.152 1.342s2.218 1.831 4.084 1.55m-16.766-3.25s-2.765 1.587-4.98.358m5.154 1.342s-1.966 1.831-3.832 1.55m14.068-1.755c-.883 1.534-4.037 1.943-4.037-1.125v-1.739m-4.038 2.864c.883 1.534 4.038 1.943 4.038-1.125v-1.739" stroke="#562E11" stroke-width=".645" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M217.471 32.91c.291-.261 3.192 1.19 3.086 1.728-.107.537-1.164 1.045-2.147.372-.983-.674-1.23-1.839-.939-2.1Zm12.15-.035c-.297-.267-3.261 1.217-3.152 1.765.109.549 1.189 1.068 2.193.38 1.004-.688 1.256-1.878.959-2.145Z" fill="#562E11"/> <path d="M217.471 32.91c.291-.261 3.192 1.19 3.086 1.728-.107.537-1.164 1.045-2.147.372-.983-.674-1.23-1.839-.939-2.1Zm12.15-.035c-.297-.267-3.261 1.217-3.152 1.765.109.549 1.189 1.068 2.193.38 1.004-.688 1.256-1.878.959-2.145Z" fill="#562E11"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="m250.988 53.697-.11-.063.452 2.944c-3.234-9.948-9.11-17.306-11.206-19.93a31.059 31.059 0 0 1-.619-.789l-.005-.007-.059-.08-.073-.1a.323.323 0 0 1-.061-.163c-.649-7.64-2.675-12.064-5.37-14.584-2.691-2.516-6.106-3.188-9.666-3.188-2.571 0-6.551.291-9.885 2.635-3.311 2.328-6.053 6.733-6.053 15.11a.321.321 0 0 1-.088.222c-1.73 1.822-9.289 10.593-12.68 22.383l.255-2.913c3.651-10.361 10.11-17.943 11.868-19.82.028-8.449 2.82-13.044 6.327-15.51 3.504-2.463 7.654-2.752 10.256-2.752 3.632 0 7.243.684 10.107 3.362 2.848 2.664 4.9 7.248 5.564 14.91l.082.111v.002c.125.169.331.426.603.766 1.89 2.364 6.985 8.737 10.361 17.454Z" fill="#562E11"/> <path fill-rule="evenodd" clip-rule="evenodd" d="m250.988 53.697-.11-.063.452 2.944c-3.234-9.948-9.11-17.306-11.206-19.93a31.059 31.059 0 0 1-.619-.789l-.005-.007-.059-.08-.073-.1a.323.323 0 0 1-.061-.163c-.649-7.64-2.675-12.064-5.37-14.584-2.691-2.516-6.106-3.188-9.666-3.188-2.571 0-6.551.291-9.885 2.635-3.311 2.328-6.053 6.733-6.053 15.11a.321.321 0 0 1-.088.222c-1.73 1.822-9.289 10.593-12.68 22.383l.255-2.913c3.651-10.361 10.11-17.943 11.868-19.82.028-8.449 2.82-13.044 6.327-15.51 3.504-2.463 7.654-2.752 10.256-2.752 3.632 0 7.243.684 10.107 3.362 2.848 2.664 4.9 7.248 5.564 14.91l.082.111v.002c.125.169.331.426.603.766 1.89 2.364 6.985 8.737 10.361 17.454Z" fill="#562E11"/>
<ellipse cx="234.613" cy="28.595" rx="2.042" ry="2.58" fill="#333" stroke="#000" stroke-width=".645"/> <ellipse cx="234.613" cy="28.595" rx="2.042" ry="2.58" fill="#333" stroke="#000" stroke-width=".645"/>
...@@ -173,7 +173,7 @@ ...@@ -173,7 +173,7 @@
<path d="M101.522 61.915a11.168 11.168 0 0 0 3.168 2.737l20.692 11.96a11.175 11.175 0 0 0 11.19 0l1.637-.945c-.715-4.798-2.489-7.243-4.08-9.436-1.739-2.398-3.261-4.495-2.941-9.04.392-5.57-.353-8.481-.999-11.003-.239-.934-.464-1.815-.613-2.758-2.56-5.59-3.746-10.222-4.126-14.142L142.8 25.8l-17.402-1.72c.187-2.314.636-4.337 1.15-6.154l.023-.08-5.809 2.608-2.723 3.012-2.007 5.822-.904 6.423c-1.485 1.522-2.856 3.095-4.471 5.813l-1.935 2.687c-.129.218-1.214 2.407-2.301 4.603h-.001l-.002.004v.002c-1.095 2.21-2.193 4.426-2.319 4.636-.367.612-1.181 3.51-1.92 6.141v.001l-.001.004-.001.003c-.231.822-.455 1.618-.655 2.31Z" fill="url(#H)"/> <path d="M101.522 61.915a11.168 11.168 0 0 0 3.168 2.737l20.692 11.96a11.175 11.175 0 0 0 11.19 0l1.637-.945c-.715-4.798-2.489-7.243-4.08-9.436-1.739-2.398-3.261-4.495-2.941-9.04.392-5.57-.353-8.481-.999-11.003-.239-.934-.464-1.815-.613-2.758-2.56-5.59-3.746-10.222-4.126-14.142L142.8 25.8l-17.402-1.72c.187-2.314.636-4.337 1.15-6.154l.023-.08-5.809 2.608-2.723 3.012-2.007 5.822-.904 6.423c-1.485 1.522-2.856 3.095-4.471 5.813l-1.935 2.687c-.129.218-1.214 2.407-2.301 4.603h-.001l-.002.004v.002c-1.095 2.21-2.193 4.426-2.319 4.636-.367.612-1.181 3.51-1.92 6.141v.001l-.001.004-.001.003c-.231.822-.455 1.618-.655 2.31Z" fill="url(#H)"/>
<path d="M101.522 61.916a11.169 11.169 0 0 0 3.168 2.736l8.644 4.996c3.337-2.408 5.6-7.084 5.6-12.458 0-7.241-4.109-13.216-9.417-14.082l-.794 1.103c-.13.217-1.214 2.407-2.302 4.602v.001c-1.096 2.213-2.195 4.432-2.321 4.642-.367.611-1.181 3.51-1.92 6.14v.001l-.001.003c-.232.825-.456 1.622-.657 2.316Zm.297 1.618.001.002c.721.713 1.538 1.34 2.438 1.86l8.267 4.78.001-.001-8.266-4.778a12.03 12.03 0 0 1-2.441-1.863Z" fill="#AE5F25"/> <path d="M101.522 61.916a11.169 11.169 0 0 0 3.168 2.736l8.644 4.996c3.337-2.408 5.6-7.084 5.6-12.458 0-7.241-4.109-13.216-9.417-14.082l-.794 1.103c-.13.217-1.214 2.407-2.302 4.602v.001c-1.096 2.213-2.195 4.432-2.321 4.642-.367.611-1.181 3.51-1.92 6.14v.001l-.001.003c-.232.825-.456 1.622-.657 2.316Zm.297 1.618.001.002c.721.713 1.538 1.34 2.438 1.86l8.267 4.78.001-.001-8.266-4.778a12.03 12.03 0 0 1-2.441-1.863Z" fill="#AE5F25"/>
<path d="M122.08 30.622c1.5-3.43 5.354-3.49 8.579-3.646 3.225.156 7.081.06 8.58 3.646 1.305 3.123-.868 9.783-2.589 11.45-2.006 1.944-4.491 1.56-5.991 1.56-1.499 0-3.984.384-5.99-1.56-1.72-1.667-3.942-8.354-2.589-11.45Z" fill="#D47B3A"/> <path d="M122.08 30.622c1.5-3.43 5.354-3.49 8.579-3.646 3.225.156 7.081.06 8.58 3.646 1.305 3.123-.868 9.783-2.589 11.45-2.006 1.944-4.491 1.56-5.991 1.56-1.499 0-3.984.384-5.99-1.56-1.72-1.667-3.942-8.354-2.589-11.45Z" fill="#D47B3A"/>
<path d="M137.383 36.42s2.765 1.587 4.981.358m-5.153 1.342s2.218 1.831 4.084 1.55m-16.766-3.25s-2.765 1.587-4.98.358m5.154 1.342s-1.965 1.831-3.832 1.55m14.069-1.755c-.884 1.534-4.038 1.943-4.038-1.125v-1.739M126.864 37.915c.884 1.534 4.038 1.943 4.038-1.125v-1.739" stroke="#562E11" stroke-width=".645" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> <path d="M137.383 36.42s2.765 1.587 4.981.358m-5.153 1.342s2.218 1.831 4.084 1.55m-16.766-3.25s-2.765 1.587-4.98.358m5.154 1.342s-1.965 1.831-3.832 1.55m14.069-1.755c-.884 1.534-4.038 1.943-4.038-1.125v-1.739m-4.038 2.864c.884 1.534 4.038 1.943 4.038-1.125v-1.739" stroke="#562E11" stroke-width=".645" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M124.69 32.91c.291-.261 3.192 1.19 3.086 1.728-.107.537-1.164 1.045-2.147.372-.983-.674-1.23-1.839-.939-2.1Zm12.15-.035c-.297-.267-3.26 1.217-3.152 1.765.109.549 1.189 1.068 2.193.38 1.004-.688 1.257-1.878.959-2.145Z" fill="#562E11"/> <path d="M124.69 32.91c.291-.261 3.192 1.19 3.086 1.728-.107.537-1.164 1.045-2.147.372-.983-.674-1.23-1.839-.939-2.1Zm12.15-.035c-.297-.267-3.26 1.217-3.152 1.765.109.549 1.189 1.068 2.193.38 1.004-.688 1.257-1.878.959-2.145Z" fill="#562E11"/>
<path d="M160.039 62.385c.185-.21.363-.425.531-.648-2.552-12.772-10.292-22.452-12.725-25.494a31.1 31.1 0 0 1-.602-.766v-.001h-.001l-.082-.112c-.664-7.662-2.715-12.246-5.564-14.91-2.863-2.678-6.474-3.361-10.106-3.361-2.602 0-6.752.288-10.256 2.751-3.507 2.466-6.299 7.061-6.327 15.51-2.103 2.245-10.937 12.66-13.638 26.229.167.228.344.45.529.666 2.57-13.853 11.738-24.515 13.665-26.545a.322.322 0 0 0 .089-.222c0-8.377 2.742-12.782 6.053-15.11 3.334-2.344 7.313-2.634 9.885-2.634 3.56 0 6.975.67 9.666 3.187 2.694 2.52 4.72 6.944 5.37 14.584.005.06.026.116.061.164l.073.1.059.08.004.005.001.001c.13.176.341.441.619.79 2.485 3.111 10.289 12.883 12.696 25.736Zm-58.979.325c.171.203.348.401.533.593l-.001.002a11.91 11.91 0 0 1-.532-.593v-.003Z" fill="#562E11"/> <path d="M160.039 62.385c.185-.21.363-.425.531-.648-2.552-12.772-10.292-22.452-12.725-25.494a31.1 31.1 0 0 1-.602-.766v-.001h-.001l-.082-.112c-.664-7.662-2.715-12.246-5.564-14.91-2.863-2.678-6.474-3.361-10.106-3.361-2.602 0-6.752.288-10.256 2.751-3.507 2.466-6.299 7.061-6.327 15.51-2.103 2.245-10.937 12.66-13.638 26.229.167.228.344.45.529.666 2.57-13.853 11.738-24.515 13.665-26.545a.322.322 0 0 0 .089-.222c0-8.377 2.742-12.782 6.053-15.11 3.334-2.344 7.313-2.634 9.885-2.634 3.56 0 6.975.67 9.666 3.187 2.694 2.52 4.72 6.944 5.37 14.584.005.06.026.116.061.164l.073.1.059.08.004.005.001.001c.13.176.341.441.619.79 2.485 3.111 10.289 12.883 12.696 25.736Zm-58.979.325c.171.203.348.401.533.593l-.001.002a11.91 11.91 0 0 1-.532-.593v-.003Z" fill="#562E11"/>
<ellipse cx="141.832" cy="28.595" rx="2.042" ry="2.58" fill="#333" stroke="#000" stroke-width=".645"/> <ellipse cx="141.832" cy="28.595" rx="2.042" ry="2.58" fill="#333" stroke="#000" stroke-width=".645"/>
......
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 99 16">
<g clip-path="url(#a)">
<mask id="b" width="99" height="16" x="0" y="0" maskUnits="userSpaceOnUse" style="mask-type:luminance">
<path fill="#fff" d="M98.647.001H0V16h98.647z"/>
</mask>
<g mask="url(#b)">
<path fill="#fff" d="M29.348.04h3.25l5.409 7.47c.873 1.19 1.867 2.887 1.867 2.887V.039h3.396v15.718h-3.275l-5.24-7.18c-1.043-1.407-2.014-3.08-2.014-3.08v10.26h-3.396V.04zm16.834 9.653c0-3.518 2.862-6.307 6.476-6.307 3.615 0 6.5 2.789 6.5 6.307 0 3.517-2.861 6.306-6.5 6.306s-6.476-2.789-6.476-6.306m9.654 0c0-1.892-1.358-3.3-3.178-3.3s-3.177 1.407-3.177 3.3 1.359 3.3 3.177 3.3 3.178-1.383 3.178-3.3m4.487-6.063h3.25l2.256 6.234c.46 1.261.849 2.522.898 2.692.024-.17.436-1.48.874-2.668l2.256-6.258h3.225l-4.779 12.15h-3.2zm13.924 6.063c0-3.494 2.716-6.307 6.282-6.307 3.3 0 5.895 2.813 5.895 6.258 0 .582-.073 1.165-.073 1.165h-8.805c.387 1.673 1.77 2.474 3.372 2.474 1.165 0 2.377-.34 3.275-.947l1.214 2.33a8.17 8.17 0 0 1-4.513 1.333c-3.542 0-6.646-2.304-6.646-6.306zm9.12-1.044c-.243-1.528-1.456-2.547-2.935-2.547s-2.62 1.02-2.935 2.547zm5.045 5.701 1.165-2.498c.824.631 1.965 1.285 3.784 1.285.75 0 1.988-.29 1.988-1.019s-1.044-.898-2.087-1.188c-2.402-.632-4.365-1.431-4.365-3.76 0-2.474 2.425-3.784 4.706-3.784 1.988 0 3.249.484 4.512 1.213l-1.092 2.426c-1.188-.582-2.304-.85-3.372-.85-.751 0-1.455.34-1.455.85 0 .68 1.02.897 2.135 1.14 2.062.484 4.317 1.382 4.317 3.857 0 2.983-3.031 3.977-5.287 3.977-2.596 0-4.269-1.019-4.949-1.649"/>
<path fill="url(#c)" d="M21.666 11.897v3.86h-2.368a15.95 15.95 0 0 1-7.292-1.764l-4.714-2.422A16 16 0 0 0 0 9.807V5.95h.933c2.536 0 5.035.604 7.29 1.762l4.717 2.422a15.96 15.96 0 0 0 7.288 1.763h1.436z"/>
<path fill="url(#d)" d="M0 11.907v3.85h6.042v-2.456A13.9 13.9 0 0 0 0 11.907"/>
<path fill="url(#e)" d="M21.666 5.95v3.858h-.937c-2.536 0-5.034-.604-7.29-1.764L8.723 5.62a15.96 15.96 0 0 0-7.29-1.763H0V0h2.366C4.902 0 7.4.604 9.655 1.762l4.719 2.424a15.95 15.95 0 0 0 7.289 1.762h.003"/>
<path fill="url(#f)" d="M21.666 3.848V0h-6.042v2.455a13.9 13.9 0 0 0 6.04 1.392z"/>
</g>
</g>
<defs>
<linearGradient id="c" x1="27.02" x2="6.463" y1=".199" y2="13.729" gradientUnits="userSpaceOnUse">
<stop stop-color="#3CF"/>
<stop offset="1" stop-color="#93C"/>
</linearGradient>
<linearGradient id="d" x1="26.026" x2="5.472" y1="-1.311" y2="12.22" gradientUnits="userSpaceOnUse">
<stop stop-color="#3CF"/>
<stop offset="1" stop-color="#93C"/>
</linearGradient>
<linearGradient id="e" x1="24.287" x2="3.732" y1="-3.951" y2="9.578" gradientUnits="userSpaceOnUse">
<stop stop-color="#3CF"/>
<stop offset="1" stop-color="#93C"/>
</linearGradient>
<linearGradient id="f" x1="25.28" x2="4.725" y1="-2.443" y2="11.086" gradientUnits="userSpaceOnUse">
<stop stop-color="#3CF"/>
<stop offset="1" stop-color="#93C"/>
</linearGradient>
<clipPath id="a">
<path fill="#fff" d="M0 0h98.667v16H0z"/>
</clipPath>
</defs>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 99 16">
<g clip-path="url(#a)">
<mask id="b" width="99" height="16" x="0" y="0" maskUnits="userSpaceOnUse" style="mask-type:luminance">
<path fill="#fff" d="M98.647.001H0V16h98.647z"/>
</mask>
<g mask="url(#b)">
<path fill="#404141" d="M29.348.04h3.25l5.409 7.47c.873 1.19 1.867 2.887 1.867 2.887V.039h3.396v15.718h-3.275l-5.24-7.18c-1.043-1.407-2.014-3.08-2.014-3.08v10.26h-3.396V.04zm16.834 9.653c0-3.518 2.862-6.307 6.476-6.307 3.615 0 6.5 2.789 6.5 6.307 0 3.517-2.861 6.306-6.5 6.306s-6.476-2.789-6.476-6.306m9.654 0c0-1.892-1.358-3.3-3.178-3.3s-3.177 1.407-3.177 3.3 1.359 3.3 3.177 3.3 3.178-1.383 3.178-3.3m4.487-6.063h3.25l2.256 6.234c.46 1.261.849 2.522.898 2.692.024-.17.436-1.48.874-2.668l2.256-6.258h3.225l-4.779 12.15h-3.2zm13.924 6.063c0-3.494 2.716-6.307 6.282-6.307 3.3 0 5.895 2.813 5.895 6.258 0 .582-.073 1.165-.073 1.165h-8.805c.387 1.673 1.77 2.474 3.372 2.474 1.165 0 2.377-.34 3.275-.947l1.214 2.33a8.17 8.17 0 0 1-4.513 1.333c-3.542 0-6.646-2.304-6.646-6.306zm9.12-1.044c-.243-1.528-1.456-2.547-2.935-2.547s-2.62 1.02-2.935 2.547zm5.045 5.701 1.165-2.498c.824.631 1.965 1.285 3.784 1.285.75 0 1.988-.29 1.988-1.019s-1.044-.898-2.087-1.188c-2.402-.632-4.365-1.431-4.365-3.76 0-2.474 2.425-3.784 4.706-3.784 1.988 0 3.249.484 4.512 1.213l-1.092 2.426c-1.188-.582-2.304-.85-3.372-.85-.751 0-1.455.34-1.455.85 0 .68 1.02.897 2.135 1.14 2.062.484 4.317 1.382 4.317 3.857 0 2.983-3.031 3.977-5.287 3.977-2.596 0-4.269-1.019-4.949-1.649"/>
<path fill="url(#c)" d="M21.666 11.897v3.86h-2.368a15.95 15.95 0 0 1-7.292-1.764l-4.714-2.422A16 16 0 0 0 0 9.807V5.95h.933c2.536 0 5.035.604 7.29 1.762l4.717 2.422a15.96 15.96 0 0 0 7.288 1.763h1.436z"/>
<path fill="url(#d)" d="M0 11.907v3.85h6.042v-2.456A13.9 13.9 0 0 0 0 11.907"/>
<path fill="url(#e)" d="M21.666 5.95v3.858h-.937c-2.536 0-5.034-.604-7.29-1.764L8.723 5.62a15.96 15.96 0 0 0-7.29-1.763H0V0h2.366C4.902 0 7.4.604 9.655 1.762l4.719 2.424a15.95 15.95 0 0 0 7.289 1.762h.003"/>
<path fill="url(#f)" d="M21.666 3.848V0h-6.042v2.455a13.9 13.9 0 0 0 6.04 1.392z"/>
</g>
</g>
<defs>
<linearGradient id="c" x1="27.02" x2="6.463" y1=".199" y2="13.729" gradientUnits="userSpaceOnUse">
<stop stop-color="#3CF"/>
<stop offset="1" stop-color="#93C"/>
</linearGradient>
<linearGradient id="d" x1="26.026" x2="5.472" y1="-1.311" y2="12.22" gradientUnits="userSpaceOnUse">
<stop stop-color="#3CF"/>
<stop offset="1" stop-color="#93C"/>
</linearGradient>
<linearGradient id="e" x1="24.287" x2="3.732" y1="-3.951" y2="9.578" gradientUnits="userSpaceOnUse">
<stop stop-color="#3CF"/>
<stop offset="1" stop-color="#93C"/>
</linearGradient>
<linearGradient id="f" x1="25.28" x2="4.725" y1="-2.443" y2="11.086" gradientUnits="userSpaceOnUse">
<stop stop-color="#3CF"/>
<stop offset="1" stop-color="#93C"/>
</linearGradient>
<clipPath id="a">
<path fill="#fff" d="M0 0h98.667v16H0z"/>
</clipPath>
</defs>
</svg>
import type { ArbitrumL2TxnBatchesItem, ArbitrumL2TxnBatch, ArbitrumL2MessagesItem } from 'types/api/arbitrumL2'; import type { ArbitrumL2TxnBatchesItem, ArbitrumL2TxnBatch, ArbitrumL2MessagesItem, ArbitrumL2TxnWithdrawalsItem } from 'types/api/arbitrumL2';
import { ADDRESS_HASH } from './addressParams'; import { ADDRESS_HASH } from './addressParams';
import { TX_HASH } from './tx'; import { TX_HASH } from './tx';
...@@ -36,3 +36,17 @@ export const ARBITRUM_L2_TXN_BATCH: ArbitrumL2TxnBatch = { ...@@ -36,3 +36,17 @@ export const ARBITRUM_L2_TXN_BATCH: ArbitrumL2TxnBatch = {
batch_data_container: 'in_blob4844', batch_data_container: 'in_blob4844',
}, },
}; };
export const ARBITRUM_L2_TXN_WITHDRAWALS_ITEM: ArbitrumL2TxnWithdrawalsItem = {
arb_block_number: 70889261,
caller: '0x507f55d716340fc836ba52c1a8daebcfeedeef1a',
completion_transaction_hash: null,
callvalue: '100000000000000',
data: '0x',
destination: '0x507f55d716340fc836ba52c1a8daebcfeedeef1a',
eth_block_number: 6494128,
id: 43685,
l2_timestamp: 1723578569,
status: 'relayed',
token: null,
};
import type * as stats from '@blockscout/stats-types';
import type { SmartContract, SmartContractMudSystemsResponse } from 'types/api/contract'; import type { SmartContract, SmartContractMudSystemsResponse } from 'types/api/contract';
import type { VerifiedContract, VerifiedContractsCounters } from 'types/api/contracts'; import type { VerifiedContract, VerifiedContractsCounters } from 'types/api/contracts';
import type { SolidityScanReport } from 'lib/solidityScan/schema'; import type { SolidityScanReport } from 'lib/solidityScan/schema';
import { ADDRESS_PARAMS, ADDRESS_HASH } from './addressParams'; import { ADDRESS_PARAMS, ADDRESS_HASH } from './addressParams';
import { STATS_COUNTER } from './stats';
export const CONTRACT_CODE_UNVERIFIED = { export const CONTRACT_CODE_UNVERIFIED = {
creation_bytecode: '0x60806040526e', creation_bytecode: '0x60806040526e',
...@@ -81,6 +83,13 @@ export const VERIFIED_CONTRACTS_COUNTERS: VerifiedContractsCounters = { ...@@ -81,6 +83,13 @@ export const VERIFIED_CONTRACTS_COUNTERS: VerifiedContractsCounters = {
new_verified_smart_contracts_24h: '1234', new_verified_smart_contracts_24h: '1234',
}; };
export const VERIFIED_CONTRACTS_COUNTERS_MICROSERVICE: stats.ContractsPageStats = {
total_contracts: STATS_COUNTER,
new_contracts_24h: STATS_COUNTER,
total_verified_contracts: STATS_COUNTER,
new_verified_contracts_24h: STATS_COUNTER,
};
export const SOLIDITY_SCAN_REPORT: SolidityScanReport = { export const SOLIDITY_SCAN_REPORT: SolidityScanReport = {
scan_report: { scan_report: {
contractname: 'BullRunners', contractname: 'BullRunners',
......
...@@ -7,8 +7,10 @@ export const POOL = { ...@@ -7,8 +7,10 @@ export const POOL = {
quote_token_address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', quote_token_address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
quote_token_symbol: 'WETH', quote_token_symbol: 'WETH',
quote_token_icon_url: 'https://coin-images.coingecko.com/coins/images/2518/small/weth.png?1696503332', quote_token_icon_url: 'https://coin-images.coingecko.com/coins/images/2518/small/weth.png?1696503332',
fully_diluted_valuation_usd: '15211385', base_token_fully_diluted_valuation_usd: '15211385',
market_cap_usd: '15211385', base_token_market_cap_usd: '15211385',
quote_token_fully_diluted_valuation_usd: '15211385',
quote_token_market_cap_usd: '15211385',
liquidity: '394101.2428', liquidity: '394101.2428',
dex: { id: 'uniswap_v2', name: 'Uniswap V2' }, dex: { id: 'uniswap_v2', name: 'Uniswap V2' },
coin_gecko_terminal_url: 'https://www.geckoterminal.com/eth/pools/0x6a1041865b76d1dc33da0257582591227c57832c', coin_gecko_terminal_url: 'https://www.geckoterminal.com/eth/pools/0x6a1041865b76d1dc33da0257582591227c57832c',
......
...@@ -42,17 +42,19 @@ export const HOMEPAGE_STATS: HomeStats = { ...@@ -42,17 +42,19 @@ export const HOMEPAGE_STATS: HomeStats = {
tvl: '1767425.102766552', tvl: '1767425.102766552',
}; };
const STATS_CHART_INFO: stats.LineChartInfo = {
id: 'chart_0',
title: 'Average transaction fee',
description: 'The average amount in ETH spent per transaction',
units: 'ETH',
resolutions: [ 'DAY', 'MONTH' ],
};
export const STATS_CHARTS_SECTION: stats.LineChartSection = { export const STATS_CHARTS_SECTION: stats.LineChartSection = {
id: 'placeholder', id: 'placeholder',
title: 'Placeholder', title: 'Placeholder',
charts: [ charts: [
{ STATS_CHART_INFO,
id: 'chart_0',
title: 'Average transaction fee',
description: 'The average amount in ETH spent per transaction',
units: 'ETH',
resolutions: [ 'DAY', 'MONTH' ],
},
{ {
id: 'chart_1', id: 'chart_1',
title: 'Transactions fees', title: 'Transactions fees',
...@@ -88,3 +90,21 @@ export const STATS_COUNTER: stats.Counter = { ...@@ -88,3 +90,21 @@ export const STATS_COUNTER: stats.Counter = {
description: 'Placeholder description', description: 'Placeholder description',
units: '', units: '',
}; };
export const HOMEPAGE_STATS_MICROSERVICE: stats.MainPageStats = {
average_block_time: STATS_COUNTER,
total_addresses: STATS_COUNTER,
total_blocks: STATS_COUNTER,
total_transactions: STATS_COUNTER,
yesterday_transactions: STATS_COUNTER,
total_operational_transactions: STATS_COUNTER,
yesterday_operational_transactions: STATS_COUNTER,
daily_new_transactions: {
chart: [],
info: STATS_CHART_INFO,
},
daily_new_operational_transactions: {
chart: [],
info: STATS_CHART_INFO,
},
};
import type * as stats from '@blockscout/stats-types';
import type { RawTracesResponse } from 'types/api/rawTrace'; import type { RawTracesResponse } from 'types/api/rawTrace';
import type { Transaction, TransactionsStats } from 'types/api/transaction'; import type { Transaction, TransactionsStats } from 'types/api/transaction';
import { ADDRESS_PARAMS } from './addressParams'; import { ADDRESS_PARAMS } from './addressParams';
import { STATS_COUNTER } from './stats';
export const TX_HASH = '0x3ed9d81e7c1001bdda1caa1dc62c0acbbe3d2c671cdc20dc1e65efdaa4186967'; export const TX_HASH = '0x3ed9d81e7c1001bdda1caa1dc62c0acbbe3d2c671cdc20dc1e65efdaa4186967';
...@@ -19,7 +21,7 @@ export const TX: Transaction = { ...@@ -19,7 +21,7 @@ export const TX: Transaction = {
type: 0, type: 0,
exchange_rate: '1828.71', exchange_rate: '1828.71',
to: ADDRESS_PARAMS, to: ADDRESS_PARAMS,
tx_burnt_fee: null, transaction_burnt_fee: null,
max_fee_per_gas: null, max_fee_per_gas: null,
result: 'success', result: 'success',
hash: '0x2b824349b320cfa72f292ab26bf525adb00083ba9fa097141896c3c8c74567cc', hash: '0x2b824349b320cfa72f292ab26bf525adb00083ba9fa097141896c3c8c74567cc',
...@@ -66,3 +68,11 @@ export const TXS_STATS: TransactionsStats = { ...@@ -66,3 +68,11 @@ export const TXS_STATS: TransactionsStats = {
transaction_fees_sum_24h: '22184012506492688277', transaction_fees_sum_24h: '22184012506492688277',
transactions_count_24h: '992890', transactions_count_24h: '992890',
}; };
export const TXS_STATS_MICROSERVICE: stats.TransactionsPageStats = {
pending_transactions_30m: STATS_COUNTER,
transactions_24h: STATS_COUNTER,
operational_transactions_24h: STATS_COUNTER,
transactions_fee_24h: STATS_COUNTER,
average_transactions_fee_24h: STATS_COUNTER,
};
...@@ -3,6 +3,8 @@ import type { ...@@ -3,6 +3,8 @@ import type {
ValidatorsStabilityCountersResponse, ValidatorsStabilityCountersResponse,
ValidatorBlackfort, ValidatorBlackfort,
ValidatorsBlackfortCountersResponse, ValidatorsBlackfortCountersResponse,
ValidatorsZilliqaItem,
ValidatorZilliqa,
} from 'types/api/validators'; } from 'types/api/validators';
import { ADDRESS_PARAMS } from './addressParams'; import { ADDRESS_PARAMS } from './addressParams';
...@@ -32,3 +34,21 @@ export const VALIDATORS_BLACKFORT_COUNTERS: ValidatorsBlackfortCountersResponse ...@@ -32,3 +34,21 @@ export const VALIDATORS_BLACKFORT_COUNTERS: ValidatorsBlackfortCountersResponse
new_validators_counter_24h: '11', new_validators_counter_24h: '11',
validators_counter: '140', validators_counter: '140',
}; };
export const VALIDATORS_ZILLIQA_ITEM: ValidatorsZilliqaItem = {
index: 420,
bls_public_key: '0x95125dca41be848801f9bd75254f1faf1ae3194b1da53e9a5684ed7f67b729542482bc521924603b9703c33bf831a100',
balance: '1000000000000000000',
};
export const VALIDATOR_ZILLIQA: ValidatorZilliqa = {
index: 420,
bls_public_key: '0x95125dca41be848801f9bd75254f1faf1ae3194b1da53e9a5684ed7f67b729542482bc521924603b9703c33bf831a100',
balance: '1000000000000000000',
added_at_block_number: 1234567890,
control_address: ADDRESS_PARAMS,
peer_id: '1234567890',
reward_address: ADDRESS_PARAMS,
signing_address: ADDRESS_PARAMS,
stake_updated_at_block_number: 1234567890,
};
...@@ -14,10 +14,13 @@ const PRESETS = { ...@@ -14,10 +14,13 @@ const PRESETS = {
garnet: 'https://explorer.garnetchain.com', garnet: 'https://explorer.garnetchain.com',
filecoin: 'https://filecoin.blockscout.com', filecoin: 'https://filecoin.blockscout.com',
gnosis: 'https://gnosis.blockscout.com', gnosis: 'https://gnosis.blockscout.com',
mekong: 'https://mekong.blockscout.com',
neon_devnet: 'https://neon-devnet.blockscout.com',
optimism: 'https://optimism.blockscout.com', optimism: 'https://optimism.blockscout.com',
optimism_celestia: 'https://opcelestia-raspberry.gelatoscout.com', optimism_celestia: 'https://opcelestia-raspberry.gelatoscout.com',
optimism_sepolia: 'https://optimism-sepolia.blockscout.com', optimism_sepolia: 'https://optimism-sepolia.blockscout.com',
polygon: 'https://polygon.blockscout.com', polygon: 'https://polygon.blockscout.com',
rari_testnet: 'https://rari-testnet.cloud.blockscout.com',
rootstock_testnet: 'https://rootstock-testnet.blockscout.com', rootstock_testnet: 'https://rootstock-testnet.blockscout.com',
scroll_sepolia: 'https://scroll-sepolia.blockscout.com', scroll_sepolia: 'https://scroll-sepolia.blockscout.com',
shibarium: 'https://www.shibariumscan.io', shibarium: 'https://www.shibariumscan.io',
......
...@@ -2,6 +2,7 @@ import type { Transaction } from 'types/api/transaction'; ...@@ -2,6 +2,7 @@ import type { Transaction } from 'types/api/transaction';
import type { UserTags, AddressImplementation, AddressParam, AddressFilecoinParams } from './addressParams'; import type { UserTags, AddressImplementation, AddressParam, AddressFilecoinParams } from './addressParams';
import type { Block, EpochRewardsType } from './block'; import type { Block, EpochRewardsType } from './block';
import type { SmartContractProxyType } from './contract';
import type { InternalTransaction } from './internalTransaction'; import type { InternalTransaction } from './internalTransaction';
import type { MudWorldSchema, MudWorldTable } from './mudWorlds'; import type { MudWorldSchema, MudWorldTable } from './mudWorlds';
import type { NFTTokenType, TokenInfo, TokenInstance, TokenType } from './token'; import type { NFTTokenType, TokenInfo, TokenInstance, TokenType } from './token';
...@@ -31,6 +32,7 @@ export interface Address extends UserTags { ...@@ -31,6 +32,7 @@ export interface Address extends UserTags {
name: string | null; name: string | null;
token: TokenInfo | null; token: TokenInfo | null;
watchlist_address_id: number | null; watchlist_address_id: number | null;
proxy_type?: SmartContractProxyType | null;
} }
export interface AddressZilliqaParams { export interface AddressZilliqaParams {
......
import type { AddressMetadataTagApi } from './addressMetadata'; import type { AddressMetadataTagApi } from './addressMetadata';
import type { SmartContractProxyType } from './contract';
export interface AddressImplementation { export interface AddressImplementation {
address: string; address: string;
...@@ -59,6 +60,7 @@ export type AddressParamBasic = { ...@@ -59,6 +60,7 @@ export type AddressParamBasic = {
tags: Array<AddressMetadataTagApi>; tags: Array<AddressMetadataTagApi>;
} | null; } | null;
filecoin?: AddressFilecoinParams; filecoin?: AddressFilecoinParams;
proxy_type?: SmartContractProxyType | null;
}; };
export type AddressParam = UserTags & AddressParamBasic; export type AddressParam = UserTags & AddressParamBasic;
...@@ -2,7 +2,7 @@ import type { AddressParam } from './addressParams'; ...@@ -2,7 +2,7 @@ import type { AddressParam } from './addressParams';
import type { TokenInfo } from './token'; import type { TokenInfo } from './token';
export type AdvancedFilterParams = { export type AdvancedFilterParams = {
tx_types?: Array<AdvancedFilterType>; transaction_types?: Array<AdvancedFilterType>;
methods?: Array<string>; methods?: Array<string>;
methods_names?: Array<string>; /* frontend only */ methods_names?: Array<string>; /* frontend only */
age_from?: string; age_from?: string;
......
...@@ -12,6 +12,8 @@ export interface ArbitrumLatestDepositsResponse { ...@@ -12,6 +12,8 @@ export interface ArbitrumLatestDepositsResponse {
items: Array<ArbitrumLatestDepositsItem>; items: Array<ArbitrumLatestDepositsItem>;
} }
export type ArbitrumL2MessageStatus = 'initiated' | 'sent' | 'confirmed' | 'relayed';
export type ArbitrumL2MessagesItem = { export type ArbitrumL2MessagesItem = {
completion_transaction_hash: string | null; completion_transaction_hash: string | null;
id: number; id: number;
...@@ -19,7 +21,7 @@ export type ArbitrumL2MessagesItem = { ...@@ -19,7 +21,7 @@ export type ArbitrumL2MessagesItem = {
origination_timestamp: string | null; origination_timestamp: string | null;
origination_transaction_block_number: number | null; origination_transaction_block_number: number | null;
origination_transaction_hash: string; origination_transaction_hash: string;
status: 'initiated' | 'sent' | 'confirmed' | 'relayed'; status: ArbitrumL2MessageStatus;
}; };
export type ArbitrumL2MessagesResponse = { export type ArbitrumL2MessagesResponse = {
...@@ -74,8 +76,14 @@ export type ArbitrumL2TxnBatchDAAnytrust = { ...@@ -74,8 +76,14 @@ export type ArbitrumL2TxnBatchDAAnytrust = {
}>; }>;
}; };
export type ArbitrumL2TxnBatchDataAvailability = ArbitrumL2TxnBatchDAAnytrust | { export type ArbitrumL2TxnBatchDACelestia = {
batch_data_container: Exclude<BatchDataContainer, 'in_anytrust'>; batch_data_container: 'in_celestia';
height: number;
transaction_commitment: string;
};
export type ArbitrumL2TxnBatchDataAvailability = ArbitrumL2TxnBatchDAAnytrust | ArbitrumL2TxnBatchDACelestia | {
batch_data_container: Exclude<BatchDataContainer, 'in_anytrust' | 'in_celestia'>;
}; };
export type ArbitrumL2TxnBatch = { export type ArbitrumL2TxnBatch = {
...@@ -108,6 +116,36 @@ export type ArbitrumL2BatchBlocks = { ...@@ -108,6 +116,36 @@ export type ArbitrumL2BatchBlocks = {
} | null; } | null;
}; };
export interface ArbitrumL2TxnWithdrawalsItem {
arb_block_number: number;
caller: string;
callvalue: string;
completion_transaction_hash: string | null;
data: string;
destination: string;
eth_block_number: number;
id: number;
l2_timestamp: number;
status: ArbitrumL2MessageStatus;
token: {
address: string;
amount: string | null;
destination: string | null;
name: string | null;
symbol: string | null;
decimals: number | null;
} | null;
}
export interface ArbitrumL2TxnWithdrawalsResponse {
items: Array<ArbitrumL2TxnWithdrawalsItem>;
}
export interface ArbitrumL2MessageClaimResponse {
calldata: string;
outbox_address: string;
}
export const ARBITRUM_L2_TX_BATCH_STATUSES = [ export const ARBITRUM_L2_TX_BATCH_STATUSES = [
'Processed on rollup' as const, 'Processed on rollup' as const,
'Sent to base' as const, 'Sent to base' as const,
......
...@@ -25,6 +25,7 @@ export type SmartContractProxyType = ...@@ -25,6 +25,7 @@ export type SmartContractProxyType =
| 'eip1822' | 'eip1822'
| 'eip930' | 'eip930'
| 'eip2535' | 'eip2535'
| 'eip7702'
| 'master_copy' | 'master_copy'
| 'basic_implementation' | 'basic_implementation'
| 'basic_get_implementation' | 'basic_get_implementation'
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment