Skip to content
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
2c4732c
envs and feature setup
tom2drum Jan 8, 2026
e6156d3
home page layout
tom2drum Jan 8, 2026
6e6bdf8
cross-chain txs page
tom2drum Jan 8, 2026
50eee84
cross-chain transfers page
tom2drum Jan 8, 2026
a94f02e
cross-chain transfers on tx page
tom2drum Jan 9, 2026
36c8676
cross-chain messages on tx page
tom2drum Jan 9, 2026
2303b9c
cross-chain tx page
tom2drum Jan 9, 2026
7323c61
cross-chain tx details token transfers
tom2drum Jan 12, 2026
789a817
stats and counters for lists
tom2drum Jan 12, 2026
7e8a217
migrate to new API version
tom2drum Jan 12, 2026
ffe1f6d
add swagger
tom2drum Jan 12, 2026
ac6aa11
mobile lists
tom2drum Jan 13, 2026
e7da2d5
placeholder views on address page
tom2drum Jan 13, 2026
2533fc7
tests
tom2drum Jan 14, 2026
c578473
fix adaptive tabs initial state when there is only one tab in the list
tom2drum Jan 14, 2026
3913128
tweaks
tom2drum Jan 14, 2026
72e374d
bug fixes
tom2drum Jan 14, 2026
5038f8d
fix tests
tom2drum Jan 14, 2026
df072d8
update screenshots
tom2drum Jan 14, 2026
a9ee8c0
Merge branch 'main' of github.com:blockscout/frontend into tom2drum/c…
tom2drum Jan 21, 2026
0386565
migrate to new api version
tom2drum Feb 2, 2026
912f205
add chain label tooltip, copy button to txs in lists and same address…
tom2drum Feb 2, 2026
eb25c7d
Merge branch 'main' of github.com:blockscout/frontend into tom2drum/c…
tom2drum Feb 2, 2026
b3901f7
list views on address page
tom2drum Feb 3, 2026
529782b
fix tests
tom2drum Feb 3, 2026
0e3d3d3
fix links to current address in the list views
tom2drum Feb 3, 2026
9544b73
update tooltips
tom2drum Feb 3, 2026
58c7119
update tables layout
tom2drum Feb 5, 2026
883fac0
review fixes
tom2drum Feb 19, 2026
ea48bca
Merge branch 'main' of github.com:blockscout/frontend into tom2drum/c…
tom2drum Feb 19, 2026
88ab4eb
fix spelling
tom2drum Feb 19, 2026
e13f4fa
update screenshots
tom2drum Feb 19, 2026
1ab7173
update screenshot
tom2drum Feb 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/deploy-review-l2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ on:
- immutable
- mega_eth
- neon_devnet
- numine
- optimism
- optimism_sepolia
- optimism_superchain
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/deploy-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ on:
- mega_eth
- mekong
- neon_devnet
- numine
- optimism
- optimism_sepolia
- optimism_superchain
Expand Down
1 change: 1 addition & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@
"mega_eth",
"mekong",
"neon_devnet",
"numine",
"optimism",
"optimism_interop_0",
"optimism_sepolia",
Expand Down
12 changes: 12 additions & 0 deletions configs/app/apis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ const contractInfoApi = (() => {
});
})();

const interchainIndexerApi = (() => {
const apiHost = getEnvValue('NEXT_PUBLIC_INTERCHAIN_INDEXER_API_HOST');
if (!apiHost) {
return;
}

return Object.freeze({
endpoint: apiHost,
});
})();

const metadataApi = (() => {
const apiHost = getEnvValue('NEXT_PUBLIC_METADATA_SERVICE_API_HOST');
if (!apiHost) {
Expand Down Expand Up @@ -221,6 +232,7 @@ const apis: Apis = Object.freeze({
bens: bensApi,
clusters: clustersApi,
contractInfo: contractInfoApi,
interchainIndexer: interchainIndexerApi,
metadata: metadataApi,
multichainAggregator: multichainAggregatorApi,
multichainStats: multichainStatsApi,
Expand Down
22 changes: 22 additions & 0 deletions configs/app/features/crossChainTxs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { Feature } from './types';

import apis from '../apis';
import { getEnvValue } from '../utils';

const title = 'Cross-chain transactions';

const config: Feature<{}> = (() => {
if (getEnvValue('NEXT_PUBLIC_CROSS_CHAIN_TXS_ENABLED') === 'true' && apis.interchainIndexer) {
return Object.freeze({
title,
isEnabled: true,
});
}

return Object.freeze({
title,
isEnabled: false,
});
})();

export default config;
1 change: 1 addition & 0 deletions configs/app/features/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export { default as beaconChain } from './beaconChain';
export { default as bridgedTokens } from './bridgedTokens';
export { default as blockchainInteraction } from './blockchainInteraction';
export { default as celo } from './celo';
export { default as crossChainTxs } from './crossChainTxs';
export { default as csvExport } from './csvExport';
export { default as dataAvailability } from './dataAvailability';
export { default as deFiDropdown } from './deFiDropdown';
Expand Down
40 changes: 40 additions & 0 deletions configs/envs/.env.numine
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Set of ENVs for Numine network explorer
# https://numine.blockscout.com
# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=numine"

# 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

NEXT_PUBLIC_CROSS_CHAIN_TXS_ENABLED=true
NEXT_PUBLIC_INTERCHAIN_INDEXER_API_HOST=https://interchain-indexer.k8s-dev.blockscout.com

# Instance ENVs
NEXT_PUBLIC_AD_BANNER_ENABLE_SPECIFY=true
NEXT_PUBLIC_ADDRESS_3RD_PARTY_WIDGETS=['talentprotocol','drops','blockscoutbadges','gitpoap','efp','etherscore','webacy','humanpassport','trustblock','smartmuv','humanode']
NEXT_PUBLIC_ADDRESS_3RD_PARTY_WIDGETS_CONFIG_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/widgets/config.json
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
NEXT_PUBLIC_API_BASE_PATH=/
NEXT_PUBLIC_API_HOST=numine.blockscout.com
NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
NEXT_PUBLIC_MIXPANEL_CONFIG_OVERRIDES={"record_sessions_percent": 0.5,"record_heatmap_data": true}
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=NUMINE
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=NUMINE
NEXT_PUBLIC_NETWORK_ID=8021
NEXT_PUBLIC_NETWORK_NAME=Numine
NEXT_PUBLIC_NETWORK_RPC_URL=https://subnets.avax.network/numi/mainnet/rpc
NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
NEXT_PUBLIC_PUZZLE_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/capyPuzzleBadge
NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
NEXT_PUBLIC_STATS_API_HOST=https://numine.blockscout.com
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
3 changes: 2 additions & 1 deletion configs/envs/.env.pw
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ NEXT_PUBLIC_TAC_OPERATION_LIFECYCLE_API_HOST=http://localhost:3100
NEXT_PUBLIC_USER_OPS_INDEXER_API_HOST=http://localhost:3110
NEXT_PUBLIC_ZETACHAIN_SERVICE_API_HOST=http://localhost:3111
NEXT_PUBLIC_MULTICHAIN_AGGREGATOR_API_HOST=http://localhost:3012
NEXT_PUBLIC_MULTICHAIN_CLUSTER=test
NEXT_PUBLIC_MULTICHAIN_STATS_API_HOST=http://localhost:3013
NEXT_PUBLIC_INTERCHAIN_INDEXER_API_HOST=http://localhost:3014
NEXT_PUBLIC_MULTICHAIN_CLUSTER=test
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=xxx
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=xxx
NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT=['base16','bech32']
Expand Down
1 change: 1 addition & 0 deletions deploy/tools/envs-validator/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ const schema = yup
.concat(featuresSchemas.apiDocsSchema)
.concat(featuresSchemas.beaconChainSchema)
.concat(featuresSchemas.bridgedTokensSchema)
.concat(featuresSchemas.crossChainTxsSchema)
.concat(featuresSchemas.defiDropdownSchema)
.concat(featuresSchemas.highlightsConfigSchema)
.concat(featuresSchemas.marketplaceSchema)
Expand Down
19 changes: 19 additions & 0 deletions deploy/tools/envs-validator/schemas/features/crossChainTxs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as yup from 'yup';
import { urlTest } from '../../utils';

export const crossChainTxsSchema = yup
.object()
.shape({
NEXT_PUBLIC_CROSS_CHAIN_TXS_ENABLED: yup.boolean(),
NEXT_PUBLIC_INTERCHAIN_INDEXER_API_HOST: yup
.string()
.when('NEXT_PUBLIC_CROSS_CHAIN_TXS_ENABLED', {
is: (value: boolean) => value,
then: (schema) => schema.test(urlTest),
otherwise: (schema) => schema.test(
'not-exist',
'NEXT_PUBLIC_INTERCHAIN_INDEXER_API_HOST can only be used with NEXT_PUBLIC_CROSS_CHAIN_TXS_ENABLED',
value => value === undefined,
),
}),
});
1 change: 1 addition & 0 deletions deploy/tools/envs-validator/schemas/features/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from './ads';
export * from './apiDocs';
export * from './beaconChain';
export * from './bridgedToken';
export * from './crossChainTxs';
export * from './defiDropdown';
export * from './highlights';
export * from './marketplace';
Expand Down
2 changes: 2 additions & 0 deletions deploy/tools/envs-validator/test/.env.cross_chain_txs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
NEXT_PUBLIC_CROSS_CHAIN_TXS_ENABLED=true
NEXT_PUBLIC_INTERCHAIN_INDEXER_API_HOST=https://api.example.com
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[
{
"id": "8021",
"name": "Numine",
"explorer_url": "https://example.com/blockchain/numine",
"route_templates": {
"tx": "/transaction/{hash}",
"address": "/wallet/{hash}",
"token": "/address/{hash}"
}
},
{
"id": "43114",
"name": "C-Chain",
"logo": "https://example.com/logo.svg",
"explorer_url": "https://example.com/blockchain/c"
}
]
12 changes: 12 additions & 0 deletions docs/ENVS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1070,6 +1070,18 @@ This feature enables the application to act as an explorer of multiple blockchai
| NEXT_PUBLIC_MULTICHAIN_AGGREGATOR_API_HOST | `string` | Multichain aggregator API service host | Required | - | `https://multichain-aggregator.k8s-dev.blockscout.com` | v2.5.0+ |
| NEXT_PUBLIC_MULTICHAIN_STATS_API_HOST | `string` | Multichain statistics API service host | Required | - | `http://multichain-search-stats.k8s-dev.blockscout.com` | v2.5.0+ |

&nbsp;

### Cross-chain transactions

This feature enables cross-chain transaction tracking and visualization, allowing users to view transactions that span multiple blockchains. It provides detailed information about cross-chain operations and links to related transactions on different chains.

| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
| --- | --- | --- | --- | --- | --- | --- |
| NEXT_PUBLIC_CROSS_CHAIN_TXS_ENABLED | `boolean` | The flag that enables the feature | Required | - | `true` | upcoming |
| NEXT_PUBLIC_INTERCHAIN_INDEXER_API_HOST | `string` | Interchain indexer API service host used to fetch cross-chain transaction data and metadata | Required | - | `https://interchain-indexer.k8s-dev.blockscout.com` | upcoming |


&nbsp;

### Badge claim link
Expand Down
9 changes: 9 additions & 0 deletions lib/api/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ import { CONTRACT_INFO_API_RESOURCES } from './services/contractInfo';
import type { ContractInfoApiPaginationFilters, ContractInfoApiResourceName, ContractInfoApiResourcePayload } from './services/contractInfo';
import { GENERAL_API_RESOURCES } from './services/general';
import type { GeneralApiResourceName, GeneralApiResourcePayload, GeneralApiPaginationFilters, GeneralApiPaginationSorting } from './services/general';
import type {
InterchainIndexerApiPaginationFilters,
InterchainIndexerApiResourceName,
InterchainIndexerApiResourcePayload,
} from './services/interchainIndexer';
import { INTERCHAIN_INDEXER_API_RESOURCES } from './services/interchainIndexer';
import type { MetadataApiResourceName, MetadataApiResourcePayload } from './services/metadata';
import { METADATA_API_RESOURCES } from './services/metadata';
import type {
Expand Down Expand Up @@ -43,6 +49,7 @@ export const RESOURCES = {
clusters: CLUSTERS_API_RESOURCES,
contractInfo: CONTRACT_INFO_API_RESOURCES,
general: GENERAL_API_RESOURCES,
interchainIndexer: INTERCHAIN_INDEXER_API_RESOURCES,
metadata: METADATA_API_RESOURCES,
multichainAggregator: MULTICHAIN_AGGREGATOR_API_RESOURCES,
multichainStats: MULTICHAIN_STATS_API_RESOURCES,
Expand Down Expand Up @@ -79,6 +86,7 @@ R extends BensApiResourceName ? BensApiResourcePayload<R> :
R extends ClustersApiResourceName ? ClustersApiResourcePayload<R> :
R extends ContractInfoApiResourceName ? ContractInfoApiResourcePayload<R> :
R extends GeneralApiResourceName ? GeneralApiResourcePayload<R> :
R extends InterchainIndexerApiResourceName ? InterchainIndexerApiResourcePayload<R> :
R extends MetadataApiResourceName ? MetadataApiResourcePayload<R> :
R extends MultichainAggregatorApiResourceName ? MultichainAggregatorApiResourcePayload<R> :
R extends MultichainStatsApiResourceName ? MultichainStatsApiResourcePayload<R> :
Expand Down Expand Up @@ -118,6 +126,7 @@ R extends BensApiResourceName ? BensApiPaginationFilters<R> :
R extends ClustersApiResourceName ? ClustersApiPaginationFilters :
R extends GeneralApiResourceName ? GeneralApiPaginationFilters<R> :
R extends ContractInfoApiResourceName ? ContractInfoApiPaginationFilters<R> :
R extends InterchainIndexerApiResourceName ? InterchainIndexerApiPaginationFilters<R> :
R extends MultichainAggregatorApiResourceName ? MultichainAggregatorApiPaginationFilters<R> :
R extends TacOperationLifecycleApiResourceName ? TacOperationLifecycleApiPaginationFilters<R> :
R extends ZetaChainApiResourceName ? ZetaChainApiPaginationFilters<R> :
Expand Down
71 changes: 71 additions & 0 deletions lib/api/services/interchainIndexer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import type { ApiResource } from '../types';
import type * as interchainIndexer from '@blockscout/interchain-indexer-types';
import type { CrossChainMessageFilters, CrossChainTransferFilters } from 'types/api/interchainIndexer';

export const INTERCHAIN_INDEXER_API_RESOURCES = {
messages: {
path: '/api/v1/interchain/messages',
filterFields: [ 'q' as const ],
paginated: true,
},
message: {
path: '/api/v1/interchain/messages/:id',
pathParams: [ 'id' as const ],
},
tx_messages: {
path: '/api/v1/interchain/messages\\:byTx/:hash',
pathParams: [ 'hash' as const ],
filterFields: [ 'q' as const ],
paginated: true,
},
address_messages: {
path: '/api/v1/interchain/messages\\:byAddress/:hash',
pathParams: [ 'hash' as const ],
paginated: true,
},
transfers: {
path: '/api/v1/interchain/transfers',
filterFields: [ 'q' as const ],
paginated: true,
},
tx_transfers: {
path: '/api/v1/interchain/transfers\\:byTx/:hash',
pathParams: [ 'hash' as const ],
filterFields: [ 'q' as const ],
paginated: true,
},
address_transfers: {
path: '/api/v1/interchain/transfers\\:byAddress/:hash',
pathParams: [ 'hash' as const ],
paginated: true,
},
stats_daily: {
path: '/api/v1/stats/daily',
},
stats_common: {
path: '/api/v1/stats/common',
},
} satisfies Record<string, ApiResource>;

export type InterchainIndexerApiResourceName = `interchainIndexer:${ keyof typeof INTERCHAIN_INDEXER_API_RESOURCES }`;

/* eslint-disable @stylistic/indent */
export type InterchainIndexerApiResourcePayload<R extends InterchainIndexerApiResourceName> =
R extends 'interchainIndexer:messages' ? interchainIndexer.GetMessagesResponse :
R extends 'interchainIndexer:message' ? interchainIndexer.InterchainMessage :
R extends 'interchainIndexer:tx_messages' ? interchainIndexer.GetMessagesResponse :
R extends 'interchainIndexer:address_messages' ? interchainIndexer.GetMessagesResponse :
R extends 'interchainIndexer:transfers' ? interchainIndexer.GetTransfersResponse :
R extends 'interchainIndexer:tx_transfers' ? interchainIndexer.GetTransfersResponse :
R extends 'interchainIndexer:address_transfers' ? interchainIndexer.GetTransfersResponse :
R extends 'interchainIndexer:stats_daily' ? interchainIndexer.GetDailyStatisticsResponse :
R extends 'interchainIndexer:stats_common' ? interchainIndexer.GetCommonStatisticsResponse :
never;
/* eslint-enable @stylistic/indent */

/* eslint-disable @stylistic/indent */
export type InterchainIndexerApiPaginationFilters<R extends InterchainIndexerApiResourceName> =
R extends 'interchainIndexer:messages' ? CrossChainMessageFilters :
R extends 'interchainIndexer:transfers' ? CrossChainTransferFilters :
never;
/* eslint-enable @stylistic/indent */
2 changes: 1 addition & 1 deletion lib/api/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export type ApiName =
'general' | 'admin' | 'bens' | 'contractInfo' | 'clusters' | 'external' |
'general' | 'admin' | 'bens' | 'contractInfo' | 'clusters' | 'external' | 'interchainIndexer' |
'metadata' | 'multichainAggregator' | 'multichainStats' | 'rewards' | 'stats' | 'tac' |
'userOps' | 'visualize' | 'zetachain';

Expand Down
1 change: 1 addition & 0 deletions lib/metadata/getPageOgType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const OG_TYPE_DICT: Record<Route['pathname'], OGPageType> = {
'/operations': 'Root page',
'/operation/[id]': 'Regular page',
'/cc/tx/[hash]': 'Regular page',
'/cross-chain-tx/[id]': 'Regular page',

// multichain routes
'/chain/[chain_slug]/accounts/label/[slug]': 'Root page',
Expand Down
1 change: 1 addition & 0 deletions lib/metadata/templates/description.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/operations': DEFAULT_TEMPLATE,
'/operation/[id]': DEFAULT_TEMPLATE,
'/cc/tx/[hash]': DEFAULT_TEMPLATE,
'/cross-chain-tx/[id]': DEFAULT_TEMPLATE,

// multichain routes
'/chain/[chain_slug]/accounts/label/[slug]': DEFAULT_TEMPLATE,
Expand Down
1 change: 1 addition & 0 deletions lib/metadata/templates/title.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/operations': '%network_name% operations',
'/operation/[id]': '%network_name% operation %id%',
'/cc/tx/[hash]': '%network_name% cross-chain transaction %hash% details',
'/cross-chain-tx/[id]': '%network_name% cross-chain transaction %id% details',

// multichain routes
'/chain/[chain_slug]/accounts/label/[slug]': '%network_name% addresses search by label',
Expand Down
1 change: 1 addition & 0 deletions lib/mixpanel/getPageType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = {
'/operations': 'Operations',
'/operation/[id]': 'Operation details',
'/cc/tx/[hash]': 'Cross-chain transaction details',
'/cross-chain-tx/[id]': 'Cross-chain transaction details',

// multichain routes
'/chain/[chain_slug]/accounts/label/[slug]': 'Chain addresses search by label',
Expand Down
27 changes: 27 additions & 0 deletions mocks/crossChain/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { ExternalChain } from 'types/externalChains';

export const config: Array<ExternalChain> = [
{
id: '43114',
name: 'C-Chain',
logo: 'https://c-chain.com/logo.svg',
explorer_url: 'https://c-chain.com/explorer',
route_templates: {
tx: '/transaction/{hash}',
address: '/wallet/{hash}',
token: '/address/{hash}',
},
},
{
id: '8021',
name: 'Numine',
logo: 'https://numine.com/logo.svg',
explorer_url: 'https://numine.com',
},
{
id: '4444',
name: 'Duck chain',
logo: undefined,
explorer_url: 'https://duck.com',
},
];
Loading
Loading