Skip to content
This repository was archived by the owner on Jan 9, 2026. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3fbbcd2
Bump brace-expansion from 1.1.11 to 1.1.12 in /deploy/tools/affected-…
dependabot[bot] Jun 25, 2025
be7b9fc
allow toaster to render custom description
tom2drum Jun 26, 2025
fdd6ade
Encode the address hash for links to the TON chain (#2813)
tom2drum Jun 27, 2025
84663f2
Support redirects for known address discrepancies (#2799)
tom2drum Jun 30, 2025
ff04dc8
Celo: support L2 epochs (#2784)
tom2drum Jun 30, 2025
2b2332c
Icons in footer links (#2809)
tom2drum Jun 30, 2025
5feb561
Metadata: send address to fetchers once visited (#2814)
tom2drum Jun 30, 2025
a01299b
Display and handle `status` field in smart contract view (#2807)
tom2drum Jul 1, 2025
843a047
OP Superchain Explorer: MVP (#2786)
tom2drum Jul 3, 2025
ad61f74
Change persistence of Mixpanel config (#2823)
tom2drum Jul 4, 2025
54a35a8
Changes in ReCaptcha behavior (#2829)
tom2drum Jul 4, 2025
a2b9c41
Address widgets (#2788)
maxaleks Jul 4, 2025
1a5f0e6
Change txs socket alert text (#2822)
isstuev Jul 4, 2025
0280f80
Inconsistent cursor when hovering over NavLinkGroup (#2831)
isstuev Jul 7, 2025
baeedfe
bump graphiql from 2.2.0 to 4.1.2
maxaleks Jul 10, 2025
045aea9
remove bots from monitoring
isstuev Jul 7, 2025
5c2218f
remove csv-export from sitemap
isstuev Jul 10, 2025
376627f
fix widgets label loading state
maxaleks Jul 11, 2025
cbaa1de
Merge pull request #2847 from blockscout/release/v2.2.0
tom2drum Jul 15, 2025
4662e86
Input/select placeholder font change (#2844)
isstuev Jul 15, 2025
319f7ff
Disable auto-zoom in inputs on mobile (#2845)
tom2drum Jul 15, 2025
17e3b6b
API documentation page (#2725)
tom2drum Jul 16, 2025
d6a8593
Merge remote-tracking branch 'upstream/main' into update/upstream
javadkh2 Jul 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
24 changes: 24 additions & 0 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ jobs:
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: yarn --frozen-lockfile

- name: Generate Chakra types
if: steps.cache-node-modules.outputs.cache-hit == 'true'
run: yarn chakra:typegen

- name: Run ESLint
run: echo "skip lint:eslint for now"

Expand Down Expand Up @@ -77,6 +81,10 @@ jobs:
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: yarn --frozen-lockfile

- name: Generate Chakra types
if: steps.cache-node-modules.outputs.cache-hit == 'true'
run: yarn chakra:typegen

- name: Install package dependencies
run: |
cd ./toolkit/package
Expand Down Expand Up @@ -136,6 +144,10 @@ jobs:
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: yarn --frozen-lockfile

- name: Generate Chakra types
if: steps.cache-node-modules.outputs.cache-hit == 'true'
run: yarn chakra:typegen

- name: Install script dependencies
run: cd ./deploy/tools/envs-validator && yarn --frozen-lockfile

Expand Down Expand Up @@ -175,6 +187,10 @@ jobs:
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: yarn --frozen-lockfile

- name: Generate Chakra types
if: steps.cache-node-modules.outputs.cache-hit == 'true'
run: yarn chakra:typegen

- name: Run Jest
run: yarn test:jest ${{ github.event_name == 'pull_request' && '--changedSince=origin/main' || '' }} --passWithNoTests

Expand Down Expand Up @@ -207,6 +223,10 @@ jobs:
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: yarn --frozen-lockfile

- name: Generate Chakra types
if: steps.cache-node-modules.outputs.cache-hit == 'true'
run: yarn chakra:typegen

- name: Install script dependencies
run: cd ./deploy/tools/affected-tests && yarn --frozen-lockfile

Expand Down Expand Up @@ -264,6 +284,10 @@ jobs:
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: yarn --frozen-lockfile

- name: Generate Chakra types
if: steps.cache-node-modules.outputs.cache-hit == 'true'
run: yarn chakra:typegen

- name: Download affected tests list
if: ${{ needs.pw_affected_tests.result == 'success' }}
uses: actions/download-artifact@v4
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/deploy-review-l2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ on:
- neon_devnet
- optimism
- optimism_sepolia
- optimism_superchain
- polygon
- rootstock
- scroll_sepolia
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/deploy-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ on:
- neon_devnet
- optimism
- optimism_sepolia
- optimism_superchain
- polygon
- rari_testnet
- rootstock
- shibarium
- scroll_sepolia
- stability
- tac
- tac_turin
- zkevm
- zilliqa_prototestnet
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/upload-source-maps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ jobs:
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: yarn --frozen-lockfile

- name: Generate Chakra types
if: steps.cache-node-modules.outputs.cache-hit == 'true'
run: yarn chakra:typegen

- name: Make production build with source maps
run: yarn build
env:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
/out/
/public/assets/envs.js
/public/assets/configs
/public/assets/multichain
/public/icons/sprite.svg
/public/icons/sprite.*.svg
/public/icons/registry.json
Expand Down
21 changes: 11 additions & 10 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"javascript.preferences.autoImportFileExcludePatterns": [
"./toolkit/package/**",
"./toolkit/components/**/index.ts",
],
"typescript.preferences.autoImportFileExcludePatterns": [
"./toolkit/package/**",
"./toolkit/components/**/index.ts",
]
}
"typescript.tsdk": "node_modules/typescript/lib",
"javascript.preferences.autoImportFileExcludePatterns": [
"./toolkit/package/**",
"./toolkit/components/**/index.ts"
],
"typescript.preferences.autoImportFileExcludePatterns": [
"./toolkit/package/**",
"./toolkit/components/**/index.ts"
],
"editor.formatOnSave": false
}
2 changes: 2 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -377,12 +377,14 @@
"optimism",
"optimism_interop_0",
"optimism_sepolia",
"optimism_superchain",
"polygon",
"rari_testnet",
"rootstock_testnet",
"scroll_sepolia",
"shibarium",
"stability_testnet",
"tac",
"tac_turin",
"zkevm",
"zilliqa_prototestnet",
Expand Down
14 changes: 14 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@
COPY ./deploy/tools/sitemap-generator/package.json ./deploy/tools/sitemap-generator/yarn.lock ./
RUN yarn --frozen-lockfile --network-timeout 100000

### MULTICHAIN CONFIG GENERATOR
# Install dependencies
WORKDIR /multichain-config-generator
COPY ./deploy/tools/multichain-config-generator/package.json ./deploy/tools/multichain-config-generator/yarn.lock ./
RUN yarn --frozen-lockfile --network-timeout 100000


# *****************************
# ****** STAGE 2: Build *******
Expand All @@ -60,7 +66,7 @@
ARG NEXT_OPEN_TELEMETRY_ENABLED
ENV NEXT_OPEN_TELEMETRY_ENABLED=$NEXT_OPEN_TELEMETRY_ENABLED

ENV NODE_ENV production

Check warning on line 69 in Dockerfile

View workflow job for this annotation

GitHub Actions / Run

Legacy key/value format with whitespace separator should not be used

LegacyKeyValueFormat: "ENV key=value" should be used instead of legacy "ENV key value" format More info: https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/

### APP
# Copy dependencies and source code
Expand Down Expand Up @@ -106,6 +112,11 @@
# Copy dependencies and source code
COPY --from=deps /sitemap-generator/node_modules ./deploy/tools/sitemap-generator/node_modules

### MULTICHAIN CONFIG GENERATOR
# Copy dependencies and source code, then build
COPY --from=deps /multichain-config-generator/node_modules ./deploy/tools/multichain-config-generator/node_modules
RUN cd ./deploy/tools/multichain-config-generator && yarn build


# *****************************
# ******* STAGE 3: Run ********
Expand All @@ -130,8 +141,11 @@
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json

# Copy tools
COPY --from=builder /app/deploy/tools/envs-validator/index.js ./envs-validator.js
COPY --from=builder /app/deploy/tools/feature-reporter/index.js ./feature-reporter.js
COPY --from=builder /app/deploy/tools/multichain-config-generator/dist ./deploy/tools/multichain-config-generator/dist

# Copy scripts
## Entripoint
Expand Down Expand Up @@ -172,6 +186,6 @@

EXPOSE 3000

ENV PORT 3000

Check warning on line 189 in Dockerfile

View workflow job for this annotation

GitHub Actions / Run

Legacy key/value format with whitespace separator should not be used

LegacyKeyValueFormat: "ENV key=value" should be used instead of legacy "ENV key value" format More info: https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/

CMD ["node", "server.js"]
35 changes: 34 additions & 1 deletion configs/app/apis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { getEnvValue } from './utils';
export interface ApiPropsBase {
endpoint: string;
basePath?: string;
socketEndpoint?: string;
}

export interface ApiPropsFull extends ApiPropsBase {
Expand Down Expand Up @@ -100,6 +101,25 @@ const rewardsApi = (() => {
});
})();

const multichainApi = (() => {
const apiHost = getEnvValue('NEXT_PUBLIC_MULTICHAIN_AGGREGATOR_API_HOST');
if (!apiHost) {
return;
}

try {
const url = new URL(apiHost);

return Object.freeze({
endpoint: apiHost,
socketEndpoint: `wss://${ url.host }`,
});
} catch (error) {
return;
}

})();

const statsApi = (() => {
const apiHost = getEnvValue('NEXT_PUBLIC_STATS_API_HOST');
if (!apiHost) {
Expand All @@ -123,6 +143,17 @@ const tacApi = (() => {
});
})();

const userOpsApi = (() => {
const apiHost = getEnvValue('NEXT_PUBLIC_USER_OPS_INDEXER_API_HOST');
if (!apiHost) {
return;
}

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

const visualizeApi = (() => {
const apiHost = getEnvValue('NEXT_PUBLIC_VISUALIZE_API_HOST');
if (!apiHost) {
Expand All @@ -135,7 +166,7 @@ const visualizeApi = (() => {
});
})();

type Apis = {
export type Apis = {
general: ApiPropsFull;
} & Partial<Record<Exclude<ApiName, 'general'>, ApiPropsBase>>;

Expand All @@ -145,9 +176,11 @@ const apis: Apis = Object.freeze({
bens: bensApi,
contractInfo: contractInfoApi,
metadata: metadataApi,
multichain: multichainApi,
rewards: rewardsApi,
stats: statsApi,
tac: tacApi,
userOps: userOpsApi,
visualize: visualizeApi,
});

Expand Down
27 changes: 27 additions & 0 deletions configs/app/features/address3rdPartyWidgets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { Feature } from './types';

import { getEnvValue, getExternalAssetFilePath, parseEnvJson } from '../utils';

// config file will be downloaded at run-time and saved in the public folder
const widgets = parseEnvJson<Array<string>>(getEnvValue('NEXT_PUBLIC_ADDRESS_3RD_PARTY_WIDGETS'));
const configUrl = getExternalAssetFilePath('NEXT_PUBLIC_ADDRESS_3RD_PARTY_WIDGETS_CONFIG_URL');

const title = 'Address 3rd party widgets';

const config: Feature<{ widgets: Array<string>; configUrl: string }> = (() => {
if (widgets && widgets.length > 0 && configUrl) {
return Object.freeze({
title,
isEnabled: true,
widgets,
configUrl,
});
}

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

export default config;
4 changes: 3 additions & 1 deletion configs/app/features/addressMetadata.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import type { Feature } from './types';

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

const title = 'Address metadata';

const config: Feature<{}> = (() => {
const config: Feature<{ isAddressTagsUpdateEnabled: boolean }> = (() => {
if (apis.metadata) {
return Object.freeze({
title,
isEnabled: true,
isAddressTagsUpdateEnabled: getEnvValue('NEXT_PUBLIC_METADATA_ADDRESS_TAGS_UPDATE_ENABLED') !== 'false',
});
}

Expand Down
40 changes: 40 additions & 0 deletions configs/app/features/apiDocs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { Feature } from './types';
import type { ApiDocsTabId } from 'types/views/apiDocs';
import { API_DOCS_TABS } from 'types/views/apiDocs';

import { getEnvValue, parseEnvJson } from '../utils';

const graphqlDefaultTxnHash = getEnvValue('NEXT_PUBLIC_GRAPHIQL_TRANSACTION');

const tabs = (() => {
const value = (parseEnvJson<Array<ApiDocsTabId>>(getEnvValue('NEXT_PUBLIC_API_DOCS_TABS')) || API_DOCS_TABS)
.filter((tab) => API_DOCS_TABS.includes(tab))
.filter((tab) => !graphqlDefaultTxnHash && tab === 'graphql_api' ? false : true);

return value.length > 0 ? value : undefined;
})();

const title = 'API documentation';

const config: Feature<{
tabs: Array<ApiDocsTabId>;
coreApiSwaggerUrl: string;
graphqlDefaultTxnHash?: string;
}> = (() => {
if (tabs) {
return Object.freeze({
title,
isEnabled: true,
tabs,
coreApiSwaggerUrl: getEnvValue('NEXT_PUBLIC_API_SPEC_URL') || `https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml`,
graphqlDefaultTxnHash,
});
}

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

export default config;
15 changes: 11 additions & 4 deletions configs/app/features/blockchainInteraction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,29 @@ import type { Feature } from './types';

import chain from '../chain';
import { getEnvValue } from '../utils';
import opSuperchain from './opSuperchain';

const walletConnectProjectId = getEnvValue('NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID');

const title = 'Blockchain interaction (writing to contract, etc.)';

const config: Feature<{ walletConnect: { projectId: string } }> = (() => {

if (
// all chain parameters are required for wagmi provider
// @wagmi/chains/dist/index.d.ts
// all chain parameters are required for wagmi provider
// @wagmi/chains/dist/index.d.ts
const isSingleChain = Boolean(
chain.id &&
chain.name &&
chain.currency.name &&
chain.currency.symbol &&
chain.currency.decimals &&
chain.rpcUrls.length > 0 &&
chain.rpcUrls.length > 0,
);

const isOpSuperchain = opSuperchain.isEnabled;

if (
(isSingleChain || isOpSuperchain) &&
walletConnectProjectId
) {
return Object.freeze({
Expand Down
4 changes: 1 addition & 3 deletions configs/app/features/celo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@ import { getEnvValue } from '../utils';

const title = 'Celo chain';

const config: Feature<{ L2UpgradeBlock: number | undefined; BLOCKS_PER_EPOCH: number }> = (() => {
const config: Feature<{ }> = (() => {

if (getEnvValue('NEXT_PUBLIC_CELO_ENABLED') === 'true') {
return Object.freeze({
title,
isEnabled: true,
L2UpgradeBlock: getEnvValue('NEXT_PUBLIC_CELO_L2_UPGRADE_BLOCK') ? Number(getEnvValue('NEXT_PUBLIC_CELO_L2_UPGRADE_BLOCK')) : undefined,
BLOCKS_PER_EPOCH: 17_280,
});
}

Expand Down
Loading
Loading