diff --git a/configs/app/features/dataAvailability.ts b/configs/app/features/dataAvailability.ts new file mode 100644 index 0000000000..add9e5fec5 --- /dev/null +++ b/configs/app/features/dataAvailability.ts @@ -0,0 +1,21 @@ +import type { Feature } from './types'; + +import { getEnvValue } from '../utils'; + +const title = 'Data availability'; + +const config: Feature<{ isEnabled: true }> = (() => { + if (getEnvValue('NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED') === 'true') { + return Object.freeze({ + title, + isEnabled: true, + }); + } + + return Object.freeze({ + title, + isEnabled: false, + }); +})(); + +export default config; diff --git a/configs/app/features/index.ts b/configs/app/features/index.ts index e2aadfda04..fbe1a6a949 100644 --- a/configs/app/features/index.ts +++ b/configs/app/features/index.ts @@ -6,6 +6,7 @@ export { default as beaconChain } from './beaconChain'; export { default as bridgedTokens } from './bridgedTokens'; export { default as blockchainInteraction } from './blockchainInteraction'; export { default as csvExport } from './csvExport'; +export { default as dataAvailability } from './dataAvailability'; export { default as gasTracker } from './gasTracker'; export { default as googleAnalytics } from './googleAnalytics'; export { default as graphqlApiDocs } from './graphqlApiDocs'; diff --git a/configs/app/ui/views/tx.ts b/configs/app/ui/views/tx.ts index 4c45a565f0..f725363504 100644 --- a/configs/app/ui/views/tx.ts +++ b/configs/app/ui/views/tx.ts @@ -1,5 +1,5 @@ -import type { TxAdditionalFieldsId, TxFieldsId, TxViewId } from 'types/views/tx'; -import { TX_ADDITIONAL_FIELDS_IDS, TX_FIELDS_IDS, TX_VIEWS_IDS } 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 { getEnvValue, parseEnvJson } from 'configs/app/utils'; @@ -33,31 +33,9 @@ const additionalFields = (() => { return result; })(); -const hiddenViews = (() => { - const envValue = getEnvValue('NEXT_PUBLIC_VIEWS_TX_HIDDEN_VIEWS'); - - if (!envValue) { - return undefined; - } - - const parsedValue = parseEnvJson>(envValue); - - if (!Array.isArray(parsedValue)) { - return undefined; - } - - const result = TX_VIEWS_IDS.reduce((result, item) => { - result[item] = parsedValue.includes(item); - return result; - }, {} as Record); - - return result; -})(); - const config = Object.freeze({ hiddenFields, additionalFields, - hiddenViews, }); export default config; diff --git a/configs/envs/.env.sepolia b/configs/envs/.env.sepolia index 25d7329dc9..72a98f40a4 100644 --- a/configs/envs/.env.sepolia +++ b/configs/envs/.env.sepolia @@ -57,6 +57,7 @@ NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true NEXT_PUBLIC_HAS_BEACON_CHAIN=true NEXT_PUBLIC_HAS_USER_OPS=true NEXT_PUBLIC_AD_BANNER_PROVIDER=getit +NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED=true #meta NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/sepolia-testnet.png diff --git a/deploy/tools/envs-validator/schema.ts b/deploy/tools/envs-validator/schema.ts index bbd0c2c619..a869772b09 100644 --- a/deploy/tools/envs-validator/schema.ts +++ b/deploy/tools/envs-validator/schema.ts @@ -32,8 +32,8 @@ import { ADDRESS_VIEWS_IDS, IDENTICON_TYPES } from '../../../types/views/address import { BLOCK_FIELDS_IDS } from '../../../types/views/block'; import type { BlockFieldId } from '../../../types/views/block'; import type { NftMarketplaceItem } from '../../../types/views/nft'; -import type { TxAdditionalFieldsId, TxFieldsId, TxViewId } from '../../../types/views/tx'; -import { TX_ADDITIONAL_FIELDS_IDS, TX_FIELDS_IDS, TX_VIEWS_IDS } 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 { replaceQuotes } from '../../../configs/app/utils'; import * as regexp from '../../../lib/regexp'; @@ -459,11 +459,6 @@ const schema = yup .transform(replaceQuotes) .json() .of(yup.string().oneOf(TX_ADDITIONAL_FIELDS_IDS)), - NEXT_PUBLIC_VIEWS_TX_HIDDEN_VIEWS: yup - .array() - .transform(replaceQuotes) - .json() - .of(yup.string().oneOf(TX_VIEWS_IDS)), NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES: yup .array() .transform(replaceQuotes) @@ -519,6 +514,7 @@ const schema = yup NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE: yup.string().oneOf(VALIDATORS_CHAIN_TYPE), NEXT_PUBLIC_GAS_TRACKER_ENABLED: yup.boolean(), NEXT_PUBLIC_GAS_TRACKER_UNITS: yup.array().transform(replaceQuotes).json().of(yup.string().oneOf(GAS_UNITS)), + NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED: yup.boolean(), // 6. External services envs NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: yup.string(), diff --git a/deploy/tools/envs-validator/test/.env.base b/deploy/tools/envs-validator/test/.env.base index 6c6f417c96..559c63fc79 100644 --- a/deploy/tools/envs-validator/test/.env.base +++ b/deploy/tools/envs-validator/test/.env.base @@ -11,6 +11,7 @@ NEXT_PUBLIC_BRIDGED_TOKENS_CHAINS=[{'id':'1','title':'Ethereum','short_title':'E NEXT_PUBLIC_BRIDGED_TOKENS_BRIDGES=[{'type':'omni','title':'OmniBridge','short_title':'OMNI'}] NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.blockscout.com/?address={hash}&blockscout={domain}','icon_url':'https://example.com/icon.svg'}] NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://example.com +NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED=true NEXT_PUBLIC_FEATURED_NETWORKS=https://example.com NEXT_PUBLIC_FOOTER_LINKS=https://example.com NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d @@ -50,7 +51,6 @@ NEXT_PUBLIC_VIEWS_BLOCK_HIDDEN_FIELDS=['burnt_fees','total_reward'] NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES=[{'name':'NFT Marketplace','collection_url':'https://example.com/{hash}','instance_url':'https://example.com/{hash}/{id}','logo_url':'https://example.com/logo.png'}] NEXT_PUBLIC_VIEWS_TX_ADDITIONAL_FIELDS=['fee_per_gas'] NEXT_PUBLIC_VIEWS_TX_HIDDEN_FIELDS=['value','fee_currency','gas_price','tx_fee','gas_fees','burnt_fees'] -NEXT_PUBLIC_VIEWS_TX_HIDDEN_VIEWS=['blob_txs'] NEXT_PUBLIC_VISUALIZE_API_HOST=https://example.com NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET=false NEXT_PUBLIC_WEB3_WALLETS=['coinbase','metamask','token_pocket'] diff --git a/deploy/values/review/values.yaml.gotmpl b/deploy/values/review/values.yaml.gotmpl index 285e7bdfc1..b2ef806295 100644 --- a/deploy/values/review/values.yaml.gotmpl +++ b/deploy/values/review/values.yaml.gotmpl @@ -86,6 +86,7 @@ frontend: NEXT_PUBLIC_AD_BANNER_ADDITIONAL_PROVIDER: adbutler 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_DATA_AVAILABILITY_ENABLED: true envFromSecret: NEXT_PUBLIC_SENTRY_DSN: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_SENTRY_DSN SENTRY_CSP_REPORT_URI: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/SENTRY_CSP_REPORT_URI diff --git a/docs/ENVS.md b/docs/ENVS.md index 9aac594d7f..f0d8faae40 100644 --- a/docs/ENVS.md +++ b/docs/ENVS.md @@ -219,7 +219,6 @@ Settings for meta tags and OG tags | --- | --- | --- | --- | --- | --- | | NEXT_PUBLIC_VIEWS_TX_HIDDEN_FIELDS | `Array` | Array of the transaction fields ids that should be hidden. See below the list of the possible id values. | - | - | `'["value","tx_fee"]'` | | NEXT_PUBLIC_VIEWS_TX_ADDITIONAL_FIELDS | `Array` | Array of the additional fields ids that should be added to the transaction details. See below the list of the possible id values. | - | - | `'["fee_per_gas"]'` | -| NEXT_PUBLIC_VIEWS_TX_HIDDEN_VIEWS | `Array` | Transaction views that should be hidden. See below the list of the possible id values. | - | - | `'["blob_txs"]'` | ##### Transaction fields list | Id | Description | @@ -236,11 +235,6 @@ Settings for meta tags and OG tags | --- | --- | | `fee_per_gas` | Amount of total fee divided by total amount of gas used by transaction | -##### Transaction view list -| Id | Description | -| --- | --- | -| `blob_txs` | List of all transactions that contain blob data | -   #### NFT views @@ -547,6 +541,16 @@ This feature allows resolving blockchain addresses using human-readable domain n   +### Data Availability + +This feature enables views related to blob transactions (EIP-4844), such as the Blob Txns tab on the Transactions page and the Blob details page. + +| Variable | Type| Description | Compulsoriness | Default value | Example value | +| --- | --- | --- | --- | --- | --- | +| NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED | `boolean` | Set to true to enable blob transactions views. | Required | - | `true` | + +  + ### Bridged tokens This feature allows users to view tokens that have been bridged from other EVM chains. Additional tab "Bridged" will be added to the tokens page and the link to original token will be displayed on the token page. diff --git a/nextjs/getServerSideProps.ts b/nextjs/getServerSideProps.ts index 39de9c0858..849e0fa3fe 100644 --- a/nextjs/getServerSideProps.ts +++ b/nextjs/getServerSideProps.ts @@ -218,6 +218,16 @@ export const gasTracker: GetServerSideProps = async(context) => { return base(context); }; +export const dataAvailability: GetServerSideProps = async(context) => { + if (!config.features.dataAvailability.isEnabled) { + return { + notFound: true, + }; + } + + return base(context); +}; + export const login: GetServerSideProps = async(context) => { if (!isNeedProxy()) { diff --git a/pages/blobs/[hash].tsx b/pages/blobs/[hash].tsx index f746e4a82c..f1056d36fa 100644 --- a/pages/blobs/[hash].tsx +++ b/pages/blobs/[hash].tsx @@ -17,4 +17,4 @@ const Page: NextPage = (props: Props) => { export default Page; -export { base as getServerSideProps } from 'nextjs/getServerSideProps'; +export { dataAvailability as getServerSideProps } from 'nextjs/getServerSideProps'; diff --git a/types/views/tx.ts b/types/views/tx.ts index dc6a750d27..21800d80e0 100644 --- a/types/views/tx.ts +++ b/types/views/tx.ts @@ -16,9 +16,3 @@ export const TX_ADDITIONAL_FIELDS_IDS = [ ] as const; export type TxAdditionalFieldsId = ArrayElement; - -export const TX_VIEWS_IDS = [ - 'blob_txs', -] as const; - -export type TxViewId = ArrayElement; diff --git a/ui/pages/Transactions.tsx b/ui/pages/Transactions.tsx index 631ac33874..4517b4d985 100644 --- a/ui/pages/Transactions.tsx +++ b/ui/pages/Transactions.tsx @@ -30,7 +30,7 @@ const Transactions = () => { const tab = getQueryParamString(router.query.tab); React.useEffect(() => { - if (tab === 'blob_txs' && config.UI.views.tx.hiddenViews?.blob_txs) { + if (tab === 'blob_txs' && !config.features.dataAvailability.isEnabled) { router.replace({ pathname: '/txs' }, undefined, { shallow: true }); } }, [ router, tab ]); @@ -66,7 +66,7 @@ const Transactions = () => { resourceName: 'txs_with_blobs', filters: { type: 'blob_transaction' }, options: { - enabled: !config.UI.views.tx.hiddenViews?.blob_txs && tab === 'blob_txs', + enabled: config.features.dataAvailability.isEnabled && tab === 'blob_txs', placeholderData: generateListStub<'txs_with_blobs'>(TX, 50, { next_page_params: { block_number: 10602877, index: 8, @@ -115,7 +115,7 @@ const Transactions = () => { /> ), }, - !config.UI.views.tx.hiddenViews?.blob_txs && { + config.features.dataAvailability.isEnabled && { id: 'blob_txs', title: 'Blob txns', component: (