Skip to content

Commit 6a99116

Browse files
authored
OP Superchain: local views for chains in the cluster (#2864)
* update styles for chain widgets on home page * update latest txs styles and slug creation algorithm * list of local txs * list of local blocks * local view for address internal tx tab * local view for address coin history * local view for address logs * local view for address token transfers * address details, kind of * [wip] local view for address contract tab * user ops views * chain popover * csv-export page * advanced filter page * block countdown pages * fixes for contract tab * refactor address txs and transfers tabs * refactor getServerSideProps * internal txs page * tokens and token transfers pages * simple tag for address page and details info placeholders * add chain icon to the local lists * show creator in contract tab * OP Superchain: local views for chains in the cluster Fixes #2827 * highlight current chain in the title of local entities * tokens nfts tab for address * allow entity icon to be an image * adjust cross-chain txs table and add placeholder to home page * cross-chain txs for address * fetch multichain config from microservice * fix skeleton in token transfers table * tests, pt.1 * wtf with gh * verified contracts page * change chain info in block and token page header * fix some tests * update styles for token icon with chain logo in header * fix links and address internal txs tab * update screenshots * fix margins for tx info button and chain icon in tx tables * add some tests * fix screenshots
1 parent adad0a2 commit 6a99116

File tree

314 files changed

+5555
-1810
lines changed

Some content is hidden

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

314 files changed

+5555
-1810
lines changed

configs/app/apis.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ const multichainApi = (() => {
113113
return Object.freeze({
114114
endpoint: apiHost,
115115
socketEndpoint: `wss://${ url.host }`,
116+
basePath: stripTrailingSlash(getEnvValue('NEXT_PUBLIC_MULTICHAIN_AGGREGATOR_BASE_PATH') || ''),
116117
});
117118
} catch (error) {
118119
return;

configs/envs/.env.optimism_superchain

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ NEXT_PUBLIC_NETWORK_ID=10
1919

2020
# TODO @tom2drum New ENVs (add to docs)
2121
NEXT_PUBLIC_MULTICHAIN_AGGREGATOR_API_HOST=https://multichain-aggregator.k8s-dev.blockscout.com
22+
NEXT_PUBLIC_MULTICHAIN_AGGREGATOR_BASE_PATH=/api/v1/clusters/interop
2223
NEXT_PUBLIC_OP_SUPERCHAIN_ENABLED=true
2324

2425
# TODO @tom2drum remove this
@@ -30,10 +31,10 @@ NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-c
3031
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=none
3132
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs', 'coin_price', 'market_cap', 'secondary_coin_price']
3233
NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['linear-gradient(90deg, rgb(232, 52, 53) 0%, rgb(139, 28, 232) 100%)'],'text_color':['rgb(255, 255, 255)']}
33-
NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/optimism-mainnet-light.svg
34-
NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/optimism-mainnet-dark.svg
35-
NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/optimism.svg
36-
NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/optimism.svg
34+
NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/optimism-superchain.svg
35+
NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/optimism-superchain.svg
36+
NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/optimism-superchain.svg
37+
NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/optimism-superchain-dark.svg
3738
NEXT_PUBLIC_NETWORK_NAME=OP Superchain
3839
NEXT_PUBLIC_NETWORK_SHORT_NAME=OP Superchain
3940
NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/optimism-mainnet.png
@@ -43,4 +44,6 @@ NEXT_PUBLIC_HIDE_INDEXING_ALERT_BLOCKS=true
4344
NEXT_PUBLIC_HIDE_INDEXING_ALERT_INT_TXS=true
4445
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=false
4546
NEXT_PUBLIC_IS_TESTNET=true
46-
NEXT_PUBLIC_USE_NEXT_JS_PROXY=false
47+
NEXT_PUBLIC_USE_NEXT_JS_PROXY=true
48+
NEXT_PUBLIC_HAS_USER_OPS=true
49+
NEXT_PUBLIC_ADVANCED_FILTER_ENABLED=false

configs/envs/.env.pw

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=http://localhost:3006
5252
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=http://localhost:3007
5353
NEXT_PUBLIC_NAME_SERVICE_API_HOST=http://localhost:3008
5454
NEXT_PUBLIC_REWARDS_SERVICE_API_HOST=http://localhost:3009
55+
NEXT_PUBLIC_MULTICHAIN_AGGREGATOR_API_HOST=http://localhost:3010
5556
NEXT_PUBLIC_TAC_OPERATION_LIFECYCLE_API_HOST=http://localhost:3100
5657
NEXT_PUBLIC_USER_OPS_INDEXER_API_HOST=http://localhost:3110
5758
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=xxx

deploy/tools/multichain-config-generator/index.ts

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,19 @@ import { Worker } from 'node:worker_threads';
66
const currentFilePath = fileURLToPath(import.meta.url);
77
const currentDir = dirname(currentFilePath);
88

9-
const EXPLORER_URLS = [
10-
'https://optimism-interop-alpha-0.blockscout.com',
11-
'https://optimism-interop-alpha-1.blockscout.com',
12-
];
13-
14-
function getSlug(url: string) {
15-
return new URL(url).hostname.replace('.blockscout.com', '').replace('.k8s-dev', '');
9+
// const EXPLORER_URLS = [
10+
// 'https://optimism.blockscout.com',
11+
// 'https://base.blockscout.com',
12+
// 'https://arbitrum.blockscout.com',
13+
// 'https://unichain.blockscout.com',
14+
// 'https://explorer.redstone.xyz',
15+
// 'https://matchscan.io'
16+
// // 'https://optimism-interop-alpha-0.blockscout.com',
17+
// // 'https://optimism-interop-alpha-1.blockscout.com',
18+
// ];
19+
20+
function getSlug(chainName: string) {
21+
return chainName.toLowerCase().replace(/ /g, '-').replace(/[^a-z0-9-]/g, '');
1622
}
1723

1824
async function computeChainConfig(url: string): Promise<unknown> {
@@ -41,6 +47,22 @@ async function computeChainConfig(url: string): Promise<unknown> {
4147
});
4248
}
4349

50+
async function getExplorerUrls() {
51+
try {
52+
const basePath = (process.env.NEXT_PUBLIC_MULTICHAIN_AGGREGATOR_BASE_PATH ?? '') + '/chains';
53+
const url = new URL(basePath, process.env.NEXT_PUBLIC_MULTICHAIN_AGGREGATOR_API_HOST);
54+
55+
const response = await fetch(url.toString());
56+
const data = await response.json();
57+
58+
console.log(`💡 Found ${ data.items.length } chains in cluster.`);
59+
60+
return data.items.map((item: { explorer_url: string }) => item.explorer_url);
61+
} catch (error) {
62+
return [];
63+
}
64+
}
65+
4466
async function run() {
4567
try {
4668
if (!process.env.NEXT_PUBLIC_MULTICHAIN_AGGREGATOR_API_HOST) {
@@ -49,12 +71,20 @@ async function run() {
4971
}
5072

5173
console.log('🌀 Generating multichain config...');
52-
const configs = await Promise.all(EXPLORER_URLS.map(computeChainConfig));
74+
75+
const explorerUrls = await getExplorerUrls();
76+
77+
if (!explorerUrls.length) {
78+
throw new Error('No chains found in the cluster.');
79+
}
80+
81+
const configs = await Promise.all(explorerUrls.map(computeChainConfig));
5382

5483
const config = {
5584
chains: configs.map((config, index) => {
85+
const chainName = (config as { chain: { name: string } })?.chain?.name ?? `Chain ${ index + 1 }`;
5686
return {
57-
slug: getSlug(EXPLORER_URLS[index]),
87+
slug: getSlug(chainName),
5888
config,
5989
};
6090
}),

deploy/tools/sitemap-generator/next-sitemap.config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@ module.exports = {
172172
};
173173
},
174174
additionalPaths: async(config) => {
175+
if(process.env.NEXT_PUBLIC_OP_SUPERCHAIN_ENABLED === 'true'){
176+
return;
177+
}
178+
175179
const addresses = fetchResource(
176180
`${ apiUrl }/addresses`,
177181
(data) => data.items.map(({ hash }) => `/address/${ hash }`),

icons/pie_chart.svg

Lines changed: 6 additions & 0 deletions
Loading

lib/api/resources.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { GENERAL_API_RESOURCES } from './services/general';
1010
import type { GeneralApiResourceName, GeneralApiResourcePayload, GeneralApiPaginationFilters, GeneralApiPaginationSorting } from './services/general';
1111
import type { MetadataApiResourceName, MetadataApiResourcePayload } from './services/metadata';
1212
import { METADATA_API_RESOURCES } from './services/metadata';
13-
import type { MultichainApiResourceName, MultichainApiResourcePayload } from './services/multichain';
13+
import type { MultichainApiPaginationFilters, MultichainApiResourceName, MultichainApiResourcePayload } from './services/multichain';
1414
import { MULTICHAIN_API_RESOURCES } from './services/multichain';
1515
import type { RewardsApiResourceName, RewardsApiResourcePayload } from './services/rewards';
1616
import { REWARDS_API_RESOURCES } from './services/rewards';
@@ -91,6 +91,7 @@ export type PaginationFilters<R extends ResourceName> =
9191
R extends BensApiResourceName ? BensApiPaginationFilters<R> :
9292
R extends GeneralApiResourceName ? GeneralApiPaginationFilters<R> :
9393
R extends ContractInfoApiResourceName ? ContractInfoApiPaginationFilters<R> :
94+
R extends MultichainApiResourceName ? MultichainApiPaginationFilters<R> :
9495
R extends TacOperationLifecycleApiResourceName ? TacOperationLifecycleApiPaginationFilters<R> :
9596
never;
9697
/* eslint-enable @stylistic/indent */

lib/api/services/multichain.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,28 @@ import type * as multichain from '@blockscout/multichain-aggregator-types';
33

44
export const MULTICHAIN_API_RESOURCES = {
55
interop_messages: {
6-
path: '/api/v1/interop/messages',
6+
path: '/messages',
7+
filterFields: [ 'address' as const ],
78
paginated: true,
89
},
10+
interop_messages_count: {
11+
path: '/messages/count',
12+
filterFields: [ 'address' as const ],
13+
},
914
} satisfies Record<string, ApiResource>;
1015

1116
export type MultichainApiResourceName = `multichain:${ keyof typeof MULTICHAIN_API_RESOURCES }`;
1217

1318
/* eslint-disable @stylistic/indent */
1419
export type MultichainApiResourcePayload<R extends MultichainApiResourceName> =
1520
R extends 'multichain:interop_messages' ? multichain.ListInteropMessagesResponse :
21+
R extends 'multichain:interop_messages_count' ? multichain.CountInteropMessagesResponse :
22+
never;
23+
/* eslint-enable @stylistic/indent */
24+
25+
/* eslint-disable @stylistic/indent */
26+
export type MultichainApiPaginationFilters<R extends MultichainApiResourceName> =
27+
R extends 'multichain:interop_messages' ? Partial<multichain.ListInteropMessagesRequest> :
28+
R extends 'multichain:interop_messages_count' ? Partial<multichain.CountInteropMessagesRequest> :
1629
never;
1730
/* eslint-enable @stylistic/indent */

lib/api/useApiFetch.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export default function useApiFetch() {
4141
const url = buildUrl(resourceName, pathParams, queryParams, undefined, chain);
4242
const withBody = isBodyAllowed(fetchParams?.method);
4343
const headers = pickBy({
44-
'x-endpoint': api.endpoint && apiName !== 'general' && isNeedProxy() ? api.endpoint : undefined,
44+
'x-endpoint': isNeedProxy() ? api.endpoint : undefined,
4545
Authorization: [ 'admin', 'contractInfo' ].includes(apiName) ? apiToken : undefined,
4646
'x-csrf-token': withBody && csrfToken ? csrfToken : undefined,
4747
...resource.headers,

lib/contexts/app.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { createContext, useContext } from 'react';
22

33
import type { Route } from 'nextjs-routes';
4-
import type { Props as PageProps } from 'nextjs/getServerSideProps';
4+
import type { Props as PageProps } from 'nextjs/getServerSideProps/handlers';
55

66
type Props = {
77
children: React.ReactNode;

0 commit comments

Comments
 (0)