Skip to content

Commit

Permalink
Show Celestia Blobs on Arbitrum chains (#2562)
Browse files Browse the repository at this point in the history
* DA info

* ENV variable

* celestia batch page

* tests

* fix ts

* [skip ci] fixes
  • Loading branch information
tom2drum authored Feb 11, 2025
1 parent 7a6ea8c commit 2747e02
Show file tree
Hide file tree
Showing 42 changed files with 380 additions and 75 deletions.
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:
- optimism_celestia
- optimism_sepolia
- polygon
- rari_testnet
- rootstock
- shibarium
- scroll_sepolia
Expand Down
1 change: 1 addition & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@
"optimism_celestia",
"optimism_sepolia",
"polygon",
"rari_testnet",
"rootstock_testnet",
"shibarium",
"stability_testnet",
Expand Down
10 changes: 10 additions & 0 deletions configs/app/features/rollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ const config: Feature<{
outputRootsEnabled: boolean;
L2WithdrawalUrl: string | undefined;
parentChainName: string | undefined;
DA: {
celestia: {
namespace: string | undefined;
};
};
}> = (() => {
if (type && L1BaseUrl) {
return Object.freeze({
Expand All @@ -36,6 +41,11 @@ const config: Feature<{
homepage: {
showLatestBlocks: getEnvValue('NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS') === 'true',
},
DA: {
celestia: {
namespace: type === 'arbitrum' ? getEnvValue('NEXT_PUBLIC_ROLLUP_DA_CELESTIA_NAMESPACE') : undefined,
},
},
});
}

Expand Down
40 changes: 40 additions & 0 deletions configs/envs/.env.rari_testnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Set of ENVs for Rari Testnet network explorer
# https://rari-testnet.cloud.blockscout.com
# This is an auto-generated file. To update all values, run "yarn dev:preset:sync --name=rari_testnet"

# 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

# Instance ENVs
NEXT_PUBLIC_AD_BANNER_PROVIDER=slise
NEXT_PUBLIC_AD_TEXT_PROVIDER=coinzilla
NEXT_PUBLIC_API_BASE_PATH=/
NEXT_PUBLIC_API_HOST=rari-testnet.cloud.blockscout.com
NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
NEXT_PUBLIC_COLOR_THEME_DEFAULT=light
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xbf69c7abc4fee283b59a9633dadfdaedde5c5ee0fba3e80a08b5b8a3acbd4363
NEXT_PUBLIC_HAS_BEACON_CHAIN=true
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND=radial-gradient(farthest-corner at 0% 0%, rgba(183, 148, 244, 0.80) 0%, rgba(0, 163, 196, 0.80) 100%)
NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR=rgb(255,255,255)
NEXT_PUBLIC_IS_TESTNET=true
NEXT_PUBLIC_NAVIGATION_HIDDEN_LINKS=[]
NEXT_PUBLIC_NAVIGATION_LAYOUT=vertical
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=ETH
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
NEXT_PUBLIC_NETWORK_ID=1
NEXT_PUBLIC_NETWORK_NAME=Rari Testnet
NEXT_PUBLIC_NETWORK_SHORT_NAME=Rari Testnet
NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=false
NEXT_PUBLIC_OTHER_LINKS=[]
NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://arbitrum-sepolia.blockscout.com/
NEXT_PUBLIC_ROLLUP_TYPE=arbitrum
NEXT_PUBLIC_SEO_ENHANCED_DATA_ENABLED=false
NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE=jazzicon
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
NEXT_PUBLIC_ROLLUP_DA_CELESTIA_NAMESPACE=0x00000000000000000000000000000000000000ca1de12a9905be97beaf
10 changes: 10 additions & 0 deletions deploy/tools/envs-validator/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,16 @@ const rollupSchema = yup
value => value === undefined,
),
}),
NEXT_PUBLIC_ROLLUP_DA_CELESTIA_NAMESPACE: yup
.string()
.min(60)
.max(60)
.matches(regexp.HEX_REGEXP_WITH_0X)
.when('NEXT_PUBLIC_ROLLUP_TYPE', {
is: (value: string) => value === 'arbitrum',
then: (schema) => schema,
otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_ROLLUP_DA_CELESTIA_NAMESPACE can only be used if NEXT_PUBLIC_ROLLUP_TYPE is set to \'arbitrum\' '),
}),
});

const celoSchema = yup
Expand Down
3 changes: 2 additions & 1 deletion deploy/tools/envs-validator/test/.env.arbitrum
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
NEXT_PUBLIC_ROLLUP_TYPE=arbitrum
NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://example.com
NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS=true
NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME=DuckChain
NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME=DuckChain
NEXT_PUBLIC_ROLLUP_DA_CELESTIA_NAMESPACE=0x00000000000000000000000000000000000000ca1de12a9905be97beaf
1 change: 1 addition & 0 deletions docs/ENVS.md
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ This feature is **enabled by default** with the `coinzilla` ads provider. To swi
| NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS | `boolean` | Set to `true` to display "Latest blocks" widget instead of "Latest batches" on the home page | - | - | `true` | v1.36.0+ |
| NEXT_PUBLIC_ROLLUP_OUTPUT_ROOTS_ENABLED | `boolean` | Enables "Output roots" page (Optimistic stack only) | - | `false` | `true` | v1.37.0+ |
| NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME | `string` | Set to customize L1 transaction status labels in the UI (e.g., "Sent to <chain-name>"). This setting is applicable only for Arbitrum-based chains. | - | - | `DuckChain` | v1.37.0+ |
| NEXT_PUBLIC_ROLLUP_DA_CELESTIA_NAMESPACE | `string` | Hex-string for creating a link to the transaction batch on the Seleneium explorer. "0x"-format and 60 symbol length. Available only for Arbitrum roll-ups. | - | - | `0x00000000000000000000000000000000000000ca1de12a9905be97beaf` | v1.38.0+ |

&nbsp;

Expand Down
12 changes: 12 additions & 0 deletions lib/api/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,11 @@ export const RESOURCES = {
pathParams: [ 'number' as const ],
},

optimistic_l2_txn_batch_celestia: {
path: '/api/v2/optimism/batches/da/celestia/:height/:commitment',
pathParams: [ 'height' as const, 'commitment' as const ],
},

optimistic_l2_txn_batch_txs: {
path: '/api/v2/transactions/optimism-batch/:number',
pathParams: [ 'number' as const ],
Expand Down Expand Up @@ -904,6 +909,11 @@ export const RESOURCES = {
pathParams: [ 'number' as const ],
},

arbitrum_l2_txn_batch_celestia: {
path: '/api/v2/arbitrum/batches/da/celestia/:height/:commitment',
pathParams: [ 'height' as const, 'commitment' as const ],
},

arbitrum_l2_txn_batch_txs: {
path: '/api/v2/transactions/arbitrum-batch/:number',
pathParams: [ 'number' as const ],
Expand Down Expand Up @@ -1339,6 +1349,7 @@ Q extends 'optimistic_l2_deposits' ? OptimisticL2DepositsResponse :
Q extends 'optimistic_l2_txn_batches' ? OptimisticL2TxnBatchesResponse :
Q extends 'optimistic_l2_txn_batches_count' ? number :
Q extends 'optimistic_l2_txn_batch' ? OptimismL2TxnBatch :
Q extends 'optimistic_l2_txn_batch_celestia' ? OptimismL2TxnBatch :
Q extends 'optimistic_l2_txn_batch_txs' ? OptimismL2BatchTxs :
Q extends 'optimistic_l2_txn_batch_blocks' ? OptimismL2BatchBlocks :
Q extends 'optimistic_l2_dispute_games' ? OptimisticL2DisputeGamesResponse :
Expand Down Expand Up @@ -1373,6 +1384,7 @@ Q extends 'arbitrum_l2_messages_count' ? number :
Q extends 'arbitrum_l2_txn_batches' ? ArbitrumL2TxnBatchesResponse :
Q extends 'arbitrum_l2_txn_batches_count' ? number :
Q extends 'arbitrum_l2_txn_batch' ? ArbitrumL2TxnBatch :
Q extends 'arbitrum_l2_txn_batch_celestia' ? ArbitrumL2TxnBatch :
Q extends 'arbitrum_l2_txn_batch_txs' ? ArbitrumL2BatchTxs :
Q extends 'arbitrum_l2_txn_batch_blocks' ? ArbitrumL2BatchBlocks :
Q extends 'zkevm_l2_deposits' ? ZkEvmL2DepositsResponse :
Expand Down
1 change: 1 addition & 0 deletions lib/metadata/getPageOgType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const OG_TYPE_DICT: Record<Route['pathname'], OGPageType> = {
'/dispute-games': 'Root page',
'/batches': 'Root page',
'/batches/[number]': 'Regular page',
'/batches/celestia/[height]/[commitment]': 'Regular page',
'/blobs/[hash]': 'Regular page',
'/ops': 'Root page',
'/op/[hash]': 'Regular 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 @@ -46,6 +46,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/dispute-games': DEFAULT_TEMPLATE,
'/batches': DEFAULT_TEMPLATE,
'/batches/[number]': DEFAULT_TEMPLATE,
'/batches/celestia/[height]/[commitment]': DEFAULT_TEMPLATE,
'/blobs/[hash]': DEFAULT_TEMPLATE,
'/ops': DEFAULT_TEMPLATE,
'/op/[hash]': 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 @@ -43,6 +43,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/dispute-games': '%network_name% dispute games',
'/batches': '%network_name% txn batches',
'/batches/[number]': '%network_name% L2 txn batch %number%',
'/batches/celestia/[height]/[commitment]': '%network_name% L2 txn batch %height% %commitment%',
'/blobs/[hash]': '%network_name% blob %hash% details',
'/ops': 'User operations on %network_name% - %network_name% explorer',
'/op/[hash]': '%network_name% user operation %hash%',
Expand Down
1 change: 1 addition & 0 deletions lib/mixpanel/getPageType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = {
'/dispute-games': 'Dispute games',
'/batches': 'Txn batches',
'/batches/[number]': 'L2 txn batch details',
'/batches/celestia/[height]/[commitment]': 'L2 txn batch details',
'/blobs/[hash]': 'Blob details',
'/ops': 'User operations',
'/op/[hash]': 'User operation details',
Expand Down
1 change: 1 addition & 0 deletions lib/regexp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export const URL_PREFIX = /^https?:\/\//i;
export const IPFS_PREFIX = /^ipfs:\/\//i;

export const HEX_REGEXP = /^(?:0x)?[\da-fA-F]+$/;
export const HEX_REGEXP_WITH_0X = /^0x[\da-fA-F]+$/;

export const FILE_EXTENSION = /\.([\da-z]+)$/i;

Expand Down
13 changes: 13 additions & 0 deletions mocks/arbitrum/txnBatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,16 @@ export const batchDataAnytrust: ArbitrumL2TxnBatch = {
],
},
};

export const batchDataCelestia: ArbitrumL2TxnBatch = {
...finalized,
after_acc: '0xcd064f3409015e8e6407e492e5275a185e492c6b43ccf127f22092d8057a9ffb',
before_acc: '0x2ed7c4985eb778d76ec400a43805e7feecc8c2afcdb492dbe5caf227de6d37bc',
start_block: 1245209,
end_block: 1245490,
data_availability: {
batch_data_container: 'in_celestia',
height: 4520041,
transaction_commitment: '0x3ebe5a43f47fbf69db003e543bb27e4875929ede2fa9a25d09f0bd082d5d20f0',
},
};
10 changes: 10 additions & 0 deletions nextjs/getServerSideProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,16 @@ export const batch: GetServerSideProps<Props> = async(context) => {
return base(context);
};

export const batchCelestia: GetServerSideProps<Props> = async(context) => {
if (!(rollupFeature.isEnabled && (rollupFeature.type === 'arbitrum' || rollupFeature.type === 'optimistic'))) {
return {
notFound: true,
};
}

return base(context);
};

export const marketplace = async <Pathname extends Route['pathname'] = never>(context: GetServerSidePropsContext):
Promise<GetServerSidePropsResult<Props<Pathname>>> => {
if (!config.features.marketplace.isEnabled) {
Expand Down
1 change: 1 addition & 0 deletions nextjs/nextjs-routes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ declare module "nextjs-routes" {
| StaticRoute<"/apps">
| StaticRoute<"/auth/profile">
| DynamicRoute<"/batches/[number]", { "number": string }>
| DynamicRoute<"/batches/celestia/[height]/[commitment]", { "height": string; "commitment": string }>
| StaticRoute<"/batches">
| DynamicRoute<"/blobs/[hash]", { "hash": string }>
| DynamicRoute<"/block/[height_or_hash]", { "height_or_hash": string }>
Expand Down
36 changes: 36 additions & 0 deletions pages/batches/celestia/[height]/[commitment].tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import React from 'react';

import type { Props } from 'nextjs/getServerSideProps';
import PageNextJs from 'nextjs/PageNextJs';

import config from 'configs/app';

const rollupFeature = config.features.rollup;

const Batch = dynamic(() => {
if (!rollupFeature.isEnabled) {
throw new Error('Rollup feature is not enabled.');
}

switch (rollupFeature.type) {
case 'arbitrum':
return import('ui/pages/ArbitrumL2TxnBatch');
case 'optimistic':
return import('ui/pages/OptimisticL2TxnBatch');
}
throw new Error('Celestia txn batches feature is not enabled.');
}, { ssr: false });

const Page: NextPage<Props> = (props: Props) => {
return (
<PageNextJs pathname="/batches/celestia/[height]/[commitment]" query={ props.query }>
<Batch/>
</PageNextJs>
);
};

export default Page;

export { batchCelestia as getServerSideProps } from 'nextjs/getServerSideProps';
1 change: 1 addition & 0 deletions playwright/fixtures/mockEnvs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const ENVS_MAP: Record<string, Array<[string, string]>> = {
[ 'NEXT_PUBLIC_ROLLUP_TYPE', 'arbitrum' ],
[ 'NEXT_PUBLIC_ROLLUP_L1_BASE_URL', 'https://localhost:3101' ],
[ 'NEXT_PUBLIC_ROLLUP_PARENT_CHAIN_NAME', 'DuckChain' ],
[ 'NEXT_PUBLIC_ROLLUP_DA_CELESTIA_NAMESPACE', '0x1234' ],
],
shibariumRollup: [
[ 'NEXT_PUBLIC_ROLLUP_TYPE', 'shibarium' ],
Expand Down
1 change: 1 addition & 0 deletions tools/preset-sync/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const PRESETS = {
optimism_celestia: 'https://opcelestia-raspberry.gelatoscout.com',
optimism_sepolia: 'https://optimism-sepolia.blockscout.com',
polygon: 'https://polygon.blockscout.com',
rari_testnet: 'https://rari-testnet.cloud.blockscout.com',
rootstock_testnet: 'https://rootstock-testnet.blockscout.com',
scroll_sepolia: 'https://scroll-sepolia.blockscout.com',
shibarium: 'https://www.shibariumscan.io',
Expand Down
10 changes: 8 additions & 2 deletions types/api/arbitrumL2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,14 @@ export type ArbitrumL2TxnBatchDAAnytrust = {
}>;
};

export type ArbitrumL2TxnBatchDataAvailability = ArbitrumL2TxnBatchDAAnytrust | {
batch_data_container: Exclude<BatchDataContainer, 'in_anytrust'>;
export type ArbitrumL2TxnBatchDACelestia = {
batch_data_container: 'in_celestia';
height: number;
transaction_commitment: string;
};

export type ArbitrumL2TxnBatchDataAvailability = ArbitrumL2TxnBatchDAAnytrust | ArbitrumL2TxnBatchDACelestia | {
batch_data_container: Exclude<BatchDataContainer, 'in_anytrust' | 'in_celestia'>;
};

export type ArbitrumL2TxnBatch = {
Expand Down
17 changes: 16 additions & 1 deletion ui/pages/ArbitrumL2TxnBatch.pw.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

import { batchData, batchDataAnytrust } from 'mocks/arbitrum/txnBatch';
import { batchData, batchDataAnytrust, batchDataCelestia } from 'mocks/arbitrum/txnBatch';
import { ENVS_MAP } from 'playwright/fixtures/mockEnvs';
import { test, expect, devices } from 'playwright/lib';

Expand Down Expand Up @@ -31,6 +31,13 @@ test('with anytrust DA', async({ render, mockApiResponse }) => {
await expect(component).toHaveScreenshot();
});

test('with celestia DA', async({ render, mockApiResponse }) => {
await mockApiResponse('arbitrum_l2_txn_batch', batchDataCelestia, { pathParams: { number: batchNumber } });
const component = await render(<ArbitrumL2TxnBatch/>, { hooksConfig });
await component.getByText('Show data availability info').click();
await expect(component).toHaveScreenshot();
});

test.describe('mobile', () => {
test.use({ viewport: devices['iPhone 13 Pro'].viewport });
test('base view', async({ render, mockApiResponse }) => {
Expand All @@ -45,4 +52,12 @@ test.describe('mobile', () => {
await component.getByText('Show data availability info').click();
await expect(component).toHaveScreenshot();
});

test('with celestia DA', async({ render, mockApiResponse, page }) => {
await mockApiResponse('arbitrum_l2_txn_batch', batchDataCelestia, { pathParams: { number: batchNumber } });
const component = await render(<ArbitrumL2TxnBatch/>, { hooksConfig });
await component.getByText('Show data availability info').click();
await page.mouse.move(0, 0);
await expect(component).toHaveScreenshot();
});
});
Loading

0 comments on commit 2747e02

Please sign in to comment.