Skip to content

Commit c251190

Browse files
tom2drumnzenchik
andauthored
OP Superchain explorer: aggregated views (#3040)
* refactor widgets on home page * coming soon placeholder component * top accounts page * contract data * address ERC-20 tokens list * chain filter for address ERC-20 tokens * token select for address detailed view * address details fields * tokens table * stats widgets on home page * chain indicators graph on the home page * quick search * search results all tab * tabs and chain select on search results page * search results mobile view * add contract info to search and address details * add text filter for tokens and search improvements * load all results inside tab on search results page * token balance info * add support for domains in the full search * Multichain explorer Resolves #2989 * add envs validator for multichain * add some tests * fix search bar on search results page on mobile * home stats fixes * fix ts * optimize amount of queries on address page * add more contract info on address page * add enter key hint to search input * fix tests * fix test * update bg.primary css-variable on color theme change * sitemap for multichain * txs page: render first tab if blob tab is not available on the chain * filter out in active chains from chain select on address page and user ops page * add chain icon to advanced filter table * fix tooltip on entity with shield * fix ts * show contract implementations * fixes * add chain icon to all lists * refactor zetachain chains config type * use chain id as primary option instead of chain slug * refactor chain config type for multichain and essential dapps * refactor chain icon and chain select * rename chain-slug in chain_slug * change default radius of chain icon and update screenshots for multichain tests * change conditions for "isContract" and "isVerified" * test fixes * make shield optional for external chain entities * add chain icon to approvals lists * add stats page for multichain * add chain postfix to chart .png and .csv assets name * fix tests * sync verified contracts language filter and fix loading state in the search results page * fix sol2uml diagram and csv export * regcred from helmfile for review * link fixes * fix state for unknown address * fix incorrect chain in the context during spa transition to the same route on different chain * add links to stats widgets * add mixpanel to L2 demo values * show message of on-demand contract verification * fix screenshots --------- Co-authored-by: Nick Zenchik <[email protected]>
1 parent 8528f25 commit c251190

File tree

386 files changed

+5946
-2580
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

386 files changed

+5946
-2580
lines changed

configs/app/apis.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ export interface ApiPropsFull extends ApiPropsBase {
1919

2020
const generalApi = (() => {
2121
const apiHost = getEnvValue('NEXT_PUBLIC_API_HOST');
22+
if (!apiHost) {
23+
return;
24+
}
25+
2226
const apiSchema = getEnvValue('NEXT_PUBLIC_API_PROTOCOL') || 'https';
2327
const apiPort = getEnvValue('NEXT_PUBLIC_API_PORT');
2428
const apiEndpoint = [
@@ -101,9 +105,10 @@ const rewardsApi = (() => {
101105
});
102106
})();
103107

104-
const multichainApi = (() => {
108+
const multichainAggregatorApi = (() => {
105109
const apiHost = getEnvValue('NEXT_PUBLIC_MULTICHAIN_AGGREGATOR_API_HOST');
106-
if (!apiHost) {
110+
const cluster = getEnvValue('NEXT_PUBLIC_MULTICHAIN_CLUSTER');
111+
if (!apiHost || !cluster) {
107112
return;
108113
}
109114

@@ -113,12 +118,22 @@ const multichainApi = (() => {
113118
return Object.freeze({
114119
endpoint: apiHost,
115120
socketEndpoint: `wss://${ url.host }`,
116-
basePath: stripTrailingSlash(getEnvValue('NEXT_PUBLIC_MULTICHAIN_AGGREGATOR_BASE_PATH') || ''),
121+
basePath: `/api/v1/clusters/${ cluster }`,
117122
});
118123
} catch (error) {
119124
return;
120125
}
126+
})();
121127

128+
const multichainStatsApi = (() => {
129+
const apiHost = getEnvValue('NEXT_PUBLIC_MULTICHAIN_STATS_API_HOST');
130+
if (!apiHost) {
131+
return;
132+
}
133+
134+
return Object.freeze({
135+
endpoint: apiHost,
136+
});
122137
})();
123138

124139
const statsApi = (() => {
@@ -197,7 +212,7 @@ const zetachainApi = (() => {
197212
})();
198213

199214
export type Apis = {
200-
general: ApiPropsFull;
215+
general: ApiPropsFull | undefined;
201216
} & Partial<Record<Exclude<ApiName, 'general'>, ApiPropsBase>>;
202217

203218
const apis: Apis = Object.freeze({
@@ -207,7 +222,8 @@ const apis: Apis = Object.freeze({
207222
clusters: clustersApi,
208223
contractInfo: contractInfoApi,
209224
metadata: metadataApi,
210-
multichain: multichainApi,
225+
multichainAggregator: multichainAggregatorApi,
226+
multichainStats: multichainStatsApi,
211227
rewards: rewardsApi,
212228
stats: statsApi,
213229
tac: tacApi,

configs/app/features/opSuperchain.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,22 @@ import type { Feature } from './types';
33
import apis from '../apis';
44
import { getEnvValue } from '../utils';
55

6-
const isEnabled = getEnvValue('NEXT_PUBLIC_OP_SUPERCHAIN_ENABLED') === 'true';
6+
const isEnabled = getEnvValue('NEXT_PUBLIC_MULTICHAIN_ENABLED') === 'true';
7+
const cluster = getEnvValue('NEXT_PUBLIC_MULTICHAIN_CLUSTER');
78

9+
// The feature was initially implemented for OP Superchain interop cluster
10+
// but later the project was abandoned by Optimism team.
11+
// Now it serves mainly for demo purposes of multichain explorer possible functionalities.
12+
// So for now I have kept all naming in the code as it was initially done
13+
// and later it could be changed when specific multichain cluster will be implemented.
814
const title = 'OP Superchain interop explorer';
915

10-
const config: Feature<{ }> = (() => {
11-
if (apis.multichain && isEnabled) {
16+
const config: Feature<{ cluster: string }> = (() => {
17+
if (apis.multichainAggregator && apis.multichainStats && isEnabled && cluster) {
1218
return Object.freeze({
1319
title,
1420
isEnabled: true,
21+
cluster,
1522
});
1623
}
1724

configs/app/features/stats.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import type { Feature } from './types';
22

33
import apis from '../apis';
4+
import opSuperchain from './opSuperchain';
45

56
const title = 'Blockchain statistics';
67

78
const config: Feature<{}> = (() => {
8-
if (apis.stats) {
9+
if (apis.stats || opSuperchain.isEnabled) {
910
return Object.freeze({
1011
title,
1112
isEnabled: true,

configs/envs/.env.optimism_superchain

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,16 @@ NEXT_PUBLIC_APP_HOST=localhost
88
NEXT_PUBLIC_APP_PORT=3000
99
NEXT_PUBLIC_APP_ENV=development
1010

11-
# Instance ENVs
12-
# TODO @tom2drum make these envs optional for multichain (adjust docs)
13-
NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
14-
NEXT_PUBLIC_API_BASE_PATH=/
15-
NEXT_PUBLIC_API_HOST=localhost
16-
NEXT_PUBLIC_API_PORT=3001
17-
NEXT_PUBLIC_API_PROTOCOL=http
18-
NEXT_PUBLIC_NETWORK_ID=10
19-
20-
# TODO @tom2drum New ENVs (add to docs)
2111
NEXT_PUBLIC_MULTICHAIN_AGGREGATOR_API_HOST=https://multichain-aggregator.k8s-dev.blockscout.com
22-
NEXT_PUBLIC_MULTICHAIN_AGGREGATOR_BASE_PATH=/api/v1/clusters/interop
23-
NEXT_PUBLIC_OP_SUPERCHAIN_ENABLED=true
12+
NEXT_PUBLIC_MULTICHAIN_STATS_API_HOST=http://multichain-search-stats.k8s-dev.blockscout.com
13+
NEXT_PUBLIC_MULTICHAIN_ENABLED=true
14+
NEXT_PUBLIC_MULTICHAIN_CLUSTER=interop
2415

25-
# TODO @tom2drum remove this
26-
SKIP_ENVS_VALIDATION=true
16+
SKIP_ENVS_VALIDATION=false
2717

28-
NEXT_PUBLIC_API_SPEC_URL=none
18+
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs','coin_price','market_cap']
19+
NEXT_PUBLIC_HOMEPAGE_STATS=['total_txs','wallet_addresses']
20+
NEXT_PUBLIC_API_DOCS_TABS=[]
2921
NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/optimism-mainnet.json
3022
NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/optimism.json
3123
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs', 'coin_price', 'market_cap', 'secondary_coin_price']
@@ -38,7 +30,6 @@ NEXT_PUBLIC_NETWORK_NAME=OP Superchain
3830
NEXT_PUBLIC_NETWORK_SHORT_NAME=OP Superchain
3931
NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/optimism-mainnet.png
4032
NEXT_PUBLIC_GAS_TRACKER_ENABLED=false
41-
NEXT_PUBLIC_NAVIGATION_HIDDEN_LINKS=['eth_rpc_api','rpc_api']
4233
NEXT_PUBLIC_HIDE_INDEXING_ALERT_BLOCKS=true
4334
NEXT_PUBLIC_HIDE_INDEXING_ALERT_INT_TXS=true
4435
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=false

configs/envs/.env.pw

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,12 @@ NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=http://localhost:3006
4949
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=http://localhost:3007
5050
NEXT_PUBLIC_NAME_SERVICE_API_HOST=http://localhost:3008
5151
NEXT_PUBLIC_REWARDS_SERVICE_API_HOST=http://localhost:3009
52-
NEXT_PUBLIC_MULTICHAIN_AGGREGATOR_API_HOST=http://localhost:3010
5352
NEXT_PUBLIC_TAC_OPERATION_LIFECYCLE_API_HOST=http://localhost:3100
5453
NEXT_PUBLIC_USER_OPS_INDEXER_API_HOST=http://localhost:3110
5554
NEXT_PUBLIC_ZETACHAIN_SERVICE_API_HOST=http://localhost:3111
55+
NEXT_PUBLIC_MULTICHAIN_AGGREGATOR_API_HOST=http://localhost:3012
56+
NEXT_PUBLIC_MULTICHAIN_CLUSTER=test
57+
NEXT_PUBLIC_MULTICHAIN_STATS_API_HOST=http://localhost:3013
5658
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=xxx
5759
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=xxx
5860
NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT=['base16','bech32']

configs/essential-dapps-chains/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import type { MultichainConfig } from 'types/multichain';
1+
import type { EssentialDappsChainConfig } from 'types/client/marketplace';
22

33
import config from 'configs/app';
44
import { isBrowser } from 'toolkit/utils/isBrowser';
55

66
const marketplaceFeature = config.features.marketplace;
77

8-
const essentialDappsChains: () => MultichainConfig | undefined = () => {
8+
const essentialDappsChains: () => { chains: Array<EssentialDappsChainConfig> } | undefined = () => {
99
if (!marketplaceFeature.isEnabled || !marketplaceFeature.essentialDapps) {
1010
return;
1111
}

deploy/tools/envs-validator/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { ValidationError } from 'yup';
55

66
import { buildExternalAssetFilePath } from '../../../configs/app/utils';
77
import schema from './schema';
8+
import schemaMultichain from './schema_multichain';
89

910
const silent = process.argv.includes('--silent');
1011

@@ -51,7 +52,12 @@ async function validateEnvs(appEnvs: Record<string, string>) {
5152
}
5253
}
5354

54-
await schema.validate(appEnvs, { stripUnknown: false, abortEarly: false });
55+
if (appEnvs.NEXT_PUBLIC_MULTICHAIN_ENABLED === 'true') {
56+
await schemaMultichain.validate(appEnvs, { stripUnknown: false, abortEarly: false });
57+
} else {
58+
await schema.validate(appEnvs, { stripUnknown: false, abortEarly: false });
59+
}
60+
5561
!silent && console.log('👍 All good!');
5662
} catch (_error) {
5763
if (typeof _error === 'object' && _error !== null && 'errors' in _error) {

0 commit comments

Comments
 (0)