Commit e2901481 authored by isstuev's avatar isstuev

output roots

parent 80c06fc8
...@@ -140,6 +140,12 @@ The app instance could be customized by passing following variables to NodeJS en ...@@ -140,6 +140,12 @@ The app instance could be customized by passing following variables to NodeJS en
| NEXT_PUBLIC_IS_L2_NETWORK | `boolean` *(optional)* | Set to true for L2 solutions (Optimism Bedrock based) | false | | NEXT_PUBLIC_IS_L2_NETWORK | `boolean` *(optional)* | Set to true for L2 solutions (Optimism Bedrock based) | false |
| NEXT_PUBLIC_L1_BASE_URL | `string` *(optional)* | Base Blockscout URL for L1 network | `'http://eth-goerli.blockscout.com'` | | NEXT_PUBLIC_L1_BASE_URL | `string` *(optional)* | Base Blockscout URL for L1 network | `'http://eth-goerli.blockscout.com'` |
### L2 configuration
| Variable | Type | Description | Default value
| --- | --- | --- | --- |
| NEXT_PUBLIC_IS_L2_NETWORK | `boolean` *(optional)* | Set to true for L2 solutions (Optimism Bedrock based) | false |
| NEXT_PUBLIC_L1_BASE_URL | `string` *(optional)* | Base Blockscout URL for L1 network | `'http://eth-goerli.blockscout.com'` |
### Marketplace app configuration properties ### Marketplace app configuration properties
| Property | Type | Description | Example value | Property | Type | Description | Example value
......
...@@ -95,6 +95,8 @@ const config = Object.freeze({ ...@@ -95,6 +95,8 @@ const config = Object.freeze({
baseUrl, baseUrl,
authUrl, authUrl,
logoutUrl, logoutUrl,
isL2Network: getEnvValue(process.env.NEXT_PUBLIC_IS_L2_NETWORK) === 'true',
l1BaseUrl: getEnvValue(process.env.NEXT_PUBLIC_L1_BASE_URL),
ad: { ad: {
domainWithAd: getEnvValue(process.env.NEXT_PUBLIC_AD_DOMAIN_WITH_AD) || 'blockscout.com', domainWithAd: getEnvValue(process.env.NEXT_PUBLIC_AD_DOMAIN_WITH_AD) || 'blockscout.com',
adButlerOn: getEnvValue(process.env.NEXT_PUBLIC_AD_ADBUTLER_ON) === 'true', adButlerOn: getEnvValue(process.env.NEXT_PUBLIC_AD_ADBUTLER_ON) === 'true',
......
This diff is collapsed.
This diff is collapsed.
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<path fill="currentColor" fill-rule="evenodd" d="M14.806 21.313H4.582A.583.583 0 0 1 4 20.731V6.179c0-.322.261-.583.582-.583h2.654V3.27c0-.321.26-.582.582-.582h7.313c.007 0 .013.002.02.004.005.001.01.003.017.003a.558.558 0 0 1 .153.031l.02.006a.575.575 0 0 1 .194.118l4.285 4.11-.002.002a.58.58 0 0 1 .181.419v9.064a1.96 1.96 0 0 1-1.958 1.959h-1.277v.95a1.96 1.96 0 0 1-1.96 1.959ZM18.31 6.798l-2.598-2.506v1.713c0 .437.356.793.793.793h1.805Zm-3.42-3.289H8.058v14.072h10.327a.794.794 0 0 0 .793-.793V7.62h-2.671c-1.08 0-1.616-.535-1.616-1.615V3.509ZM7.236 6.42H4.822v14.07H15.15c.437 0 .793-.7.793-1.136v-.951H7.818a.582.582 0 0 1-.582-.583V6.42Zm9.482 4.532a.39.39 0 1 0 0-.78h-5.12l.502-.504a.39.39 0 0 0-.55-.549l-1.168 1.169a.39.39 0 0 0 .059.599.39.39 0 0 0 .216.065h6.06Zm-.012 1.363h-6.061a.39.39 0 0 0 0 .779h5.12l-.502.504a.39.39 0 1 0 .549.55l1.168-1.17a.39.39 0 0 0-.058-.598.39.39 0 0 0-.216-.065Z" clip-rule="evenodd"/>
<path fill="currentColor" d="M7.236 5.596v.25h.25v-.25h-.25Zm7.915-2.905-.07.24.07-.24Zm.017.003.014-.25-.014.25Zm.153.031.085-.235-.003-.001-.082.236Zm.02.006.072-.239-.072.24Zm.031.012.104-.228h-.001l-.103.228Zm.162.106.173-.18-.173.18Zm4.287 4.111.177.177.18-.18-.184-.177-.173.18Zm-.002.002-.176-.177-.18.18.183.177.173-.18Zm-3.054 11.442v-.25h-.25v.25h.25ZM15.713 4.292l.174-.18-.424-.408v.588h.25Zm2.598 2.506v.25h.62l-.446-.43-.174.18ZM8.058 3.51v-.25h-.25v.25h.25Zm6.833 0h.25v-.25h-.25v.25ZM8.058 17.581h-.25v.25h.25v-.25Zm11.12-9.96h.25v-.25h-.25v.25ZM4.822 6.418v-.25h-.25v.25h.25Zm2.414 0h.25v-.25h-.25v.25ZM4.822 20.49h-.25v.25h.25v-.25Zm11.12-2.087h.25v-.25h-.25v.25Zm1.051-7.567-.177-.177.177.177Zm0-.551-.177.177.177-.177Zm-5.396-.114-.177-.177-.425.427h.602v-.25Zm.503-.505.177.177.007-.007.006-.007-.19-.163Zm.093-.268.25-.01-.25.01Zm-.114-.26.177-.177-.177.177Zm-.26-.114.01-.25-.01.25Zm-.268.093-.163-.19-.007.007-.007.007.177.176Zm-1.169 1.169.177.177-.177-.177Zm-.107.199.245.05-.245-.05Zm.022.225-.232.095.001.001.23-.096Zm.143.175.139-.209-.139.209Zm.217.065v-.25.25Zm6.049 1.363v.25-.25Zm-6.337.114.177.177-.177-.177Zm0 .55.177-.176-.177.177Zm5.396.115.177.176.425-.426h-.602v.25Zm-.502.504.162.19.008-.007.007-.007-.177-.176Zm-.098.126.225.11-.225-.11Zm-.038.155-.25-.01.25.01Zm.026.157.233-.091-.233.09Zm.088.133-.177.177.177-.177Zm.29.114-.01-.25.01.25Zm.154-.039.11.225-.11-.225Zm.127-.097-.177-.177-.007.007-.006.007.19.163Zm1.168-1.168-.176-.178v.001l.176.177Zm.086-.425.23-.095v-.001l-.23.096Zm-.144-.174-.139.208.139-.208Zm-12.34 9.184h10.224v-.5H4.582v.5Zm-.832-.832c0 .46.373.832.832.832v-.5a.333.333 0 0 1-.332-.332h-.5Zm0-14.552V20.73h.5V6.179h-.5Zm.832-.833a.833.833 0 0 0-.832.833h.5c0-.184.149-.333.332-.333v-.5Zm2.654 0H4.582v.5h2.654v-.5Zm-.25-2.077v2.327h.5V3.27h-.5Zm.832-.832a.832.832 0 0 0-.832.832h.5c0-.183.148-.332.332-.332v-.5Zm7.313 0H7.818v.5h7.313v-.5Zm.09.014c-.002 0-.041-.014-.09-.014v.5a.202.202 0 0 1-.042-.004c-.007-.002-.013-.004-.009-.002l.14-.48Zm-.04-.006a.2.2 0 0 1 .034.004l.006.002-.14.48s.034.01.073.013l.027-.5Zm.222.044a.808.808 0 0 0-.22-.044l-.03.499a.307.307 0 0 1 .085.017l.165-.472Zm.01.003a2.077 2.077 0 0 1-.007-.002s-.001 0 0 0l-.17.47.032.01.145-.478Zm.062.022a.443.443 0 0 0-.062-.022l-.145.479a.198.198 0 0 1 .008.002l-.006-.002.205-.457Zm.232.154a.823.823 0 0 0-.231-.153l-.208.455c.041.018.07.038.093.06l.346-.362Zm4.287 4.112-4.287-4.111-.346.36 4.287 4.112.346-.361Zm.002.359.002-.002-.354-.354-.001.002.353.354Zm.254.242a.83.83 0 0 0-.257-.6l-.347.361a.33.33 0 0 1 .104.239h.5Zm0 9.064V7.381h-.5v9.064h.5Zm-2.208 2.209a2.21 2.21 0 0 0 2.208-2.209h-.5a1.71 1.71 0 0 1-1.708 1.709v.5Zm-1.277 0h1.277v-.5h-1.277v.5Zm.25.7v-.95h-.5v.95h.5Zm-2.21 2.209a2.21 2.21 0 0 0 2.21-2.208h-.5a1.71 1.71 0 0 1-1.71 1.708v.5Zm.735-17.09 2.598 2.505.347-.36-2.598-2.506-.348.36Zm.423 1.532V4.292h-.5v1.713h.5Zm.543.543a.544.544 0 0 1-.543-.543h-.5c0 .575.468 1.043 1.043 1.043v-.5Zm1.805 0h-1.805v.5h1.805v-.5ZM8.058 3.76h6.833v-.5H8.058v.5Zm.25 13.822V3.51h-.5v14.072h.5Zm10.077-.25H8.058v.5h10.327v-.5Zm.543-.543c0 .3-.244.543-.543.543v.5c.575 0 1.043-.468 1.043-1.043h-.5Zm0-9.168v9.168h.5V7.62h-.5Zm-2.421.25h2.67v-.5h-2.67v.5ZM14.64 6.005c0 .578.143 1.057.476 1.39.333.332.812.475 1.39.475v-.5c-.502 0-.831-.124-1.037-.33-.205-.205-.33-.533-.33-1.035h-.5Zm0-2.496v2.496h.5V3.509h-.5ZM4.822 6.67h2.414v-.5H4.822v.5Zm.25 13.822V6.419h-.5V20.49h.5Zm10.077-.25H4.822v.5h10.326v-.5Zm.543-.886c0 .162-.07.401-.195.599-.13.21-.264.287-.348.287v.5c.352 0 .616-.272.772-.522.164-.26.27-.59.27-.864h-.5Zm0-.951v.95h.5v-.95h-.5Zm-7.874.25h8.124v-.5H7.818v.5Zm-.832-.833c0 .46.372.833.832.833v-.5a.332.332 0 0 1-.332-.333h-.5Zm0-11.402v11.4h.5V6.42h-.5Zm9.83 4.24a.14.14 0 0 1-.098.042v.5a.64.64 0 0 0 .452-.188l-.354-.353Zm.041-.098a.14.14 0 0 1-.04.099l.353.353a.64.64 0 0 0 .187-.452h-.5Zm-.04-.098a.14.14 0 0 1 .04.098h.5a.64.64 0 0 0-.187-.452l-.354.354Zm-.1-.041a.14.14 0 0 1 .1.04l.353-.353a.64.64 0 0 0-.452-.187v.5Zm-5.12 0h5.12v-.5h-5.12v.5Zm.326-.931-.503.504.355.353.502-.504-.354-.353Zm.02-.082a.14.14 0 0 1-.033.096l.38.325a.64.64 0 0 0 .153-.44l-.5.019Zm-.04-.093a.14.14 0 0 1 .04.093l.5-.02a.64.64 0 0 0-.187-.427l-.353.354Zm-.094-.041a.14.14 0 0 1 .094.04l.353-.353a.64.64 0 0 0-.427-.187l-.02.5Zm-.096.033a.14.14 0 0 1 .096-.033l.02-.5a.64.64 0 0 0-.44.153l.324.38Zm-1.154 1.155 1.168-1.168-.353-.353-1.168 1.168.353.354Zm-.039.072a.139.139 0 0 1 .039-.071l-.353-.355a.64.64 0 0 0-.176.328l.49.098Zm.008.081a.139.139 0 0 1-.008-.08l-.49-.1a.64.64 0 0 0 .036.37l.462-.19Zm.05.061a.14.14 0 0 1-.05-.062l-.462.192c.049.117.13.217.236.287l.277-.417Zm.078.024a.14.14 0 0 1-.077-.024l-.277.417a.64.64 0 0 0 .356.107l-.002-.5Zm6.062 0h-6.061v.5h6.06v-.5Zm-6.073 1.863h6.06v-.5h-6.06v.5Zm-.099.04a.14.14 0 0 1 .099-.04v-.5a.64.64 0 0 0-.452.187l.353.354Zm-.04.1a.14.14 0 0 1 .04-.1l-.353-.353a.639.639 0 0 0-.188.452h.5Zm.04.098a.14.14 0 0 1-.04-.099h-.5c0 .17.067.333.187.452l.353-.353Zm.099.04a.14.14 0 0 1-.099-.04l-.353.353a.64.64 0 0 0 .452.188v-.5Zm5.12 0h-5.12v.5h5.12v-.5Zm-.325.931.502-.504-.354-.353-.502.505.354.352Zm-.05.06a.138.138 0 0 1 .035-.046l-.325-.38a.639.639 0 0 0-.16.207l.45.218Zm-.014.054a.14.14 0 0 1 .014-.055l-.45-.218a.64.64 0 0 0-.063.254l.5.02Zm.01.057a.139.139 0 0 1-.01-.057l-.5-.019a.64.64 0 0 0 .045.258l.465-.182Zm.031.047a.139.139 0 0 1-.03-.047l-.466.182a.64.64 0 0 0 .143.219l.353-.354Zm.048.032a.139.139 0 0 1-.048-.032l-.353.354a.64.64 0 0 0 .219.143l.182-.465Zm.056.01a.139.139 0 0 1-.056-.01l-.182.465a.64.64 0 0 0 .258.044l-.02-.5Zm.056-.015a.138.138 0 0 1-.056.014l.02.5a.64.64 0 0 0 .253-.064l-.217-.45Zm.045-.035a.138.138 0 0 1-.045.035l.217.45a.64.64 0 0 0 .208-.16l-.38-.325Zm1.181-1.182-1.168 1.168.354.354 1.168-1.168-.354-.354Zm.04-.072a.139.139 0 0 1-.04.071l.353.355a.64.64 0 0 0 .176-.327l-.49-.099Zm-.009-.08a.14.14 0 0 1 .008.08l.49.099a.64.64 0 0 0-.035-.37l-.463.19Zm-.05-.062a.14.14 0 0 1 .051.063l.461-.193a.64.64 0 0 0-.236-.286l-.276.416Zm-.078-.023a.14.14 0 0 1 .078.023l.276-.416a.639.639 0 0 0-.355-.107l.001.5Z"/>
</svg>
import type { NextPage } from 'next';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import OutputRoots from 'ui/pages/OutputRoots';
const TokensPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head>
<title>{ title }</title>
</Head>
<OutputRoots/>
</>
);
};
export default TokensPage;
export { getServerSideProps } from 'lib/next/getServerSidePropsL2';
export type OutputRootsItem = {
l1_block_number: number;
l1_timestamp: string;
l1_tx_hash: string;
l2_block_number: number;
l2_output_index: number;
output_root: string;
}
export type OutputRootsResponse = {
items: Array<OutputRootsItem>;
next_page_params: {
index: number;
items_count: number;
};
}
/* eslint-disable @typescript-eslint/naming-convention */
import { Box, Flex, Text, HStack, Icon } from '@chakra-ui/react';
import React from 'react';
import type { OutputRootsItem } from 'types/api/outputRoots';
import txIcon from 'icons/transactions.svg';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import link from 'lib/link/link';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal';
import ListItemMobile from 'ui/shared/ListItemMobile';
type Props = OutputRootsItem;
const OutputRootsListItem = ({
l2_output_index,
l1_timestamp,
l2_block_number,
l1_tx_hash,
output_root,
}: Props) => {
const url = link('tx', { id: l1_tx_hash });
const timeAgo = useTimeAgoIncrement(l1_timestamp, false);
return (
<ListItemMobile rowGap={ 3 }>
<Flex alignItems="center" justifyContent="space-between" w="100%">
#{ l2_output_index }
{ l1_timestamp && <Text variant="secondary" fontWeight="400" fontSize="sm">{ timeAgo }</Text> }
</Flex>
<HStack spacing={ 3 }>
<Text fontSize="sm" fontWeight={ 500 }>L2 block</Text>
<LinkInternal display="flex" alignItems="center" href={ link('block', { id: l2_block_number.toString() }) }>
{ l2_block_number }
</LinkInternal>
</HStack>
<HStack spacing={ 3 } width="100%">
<Text fontSize="sm" fontWeight={ 500 } whiteSpace="nowrap">Output root</Text>
<Flex overflow="hidden" whiteSpace="nowrap" alignItems="center" w="100%">
<Text variant="secondary" w="calc(100% - 36px)"><HashStringShortenDynamic hash={ output_root }/></Text>
<CopyToClipboard text={ output_root } ml={ 2 }/>
</Flex>
</HStack>
<LinkExternal href={ url } w="100%">
<Icon as={ txIcon } boxSize={ 6 } mr={ 1 }/>
<Box w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap"><HashStringShortenDynamic hash={ l1_tx_hash }/></Box>
</LinkExternal>
</ListItemMobile>
);
};
export default OutputRootsListItem;
import { Table, Tbody, Th, Tr } from '@chakra-ui/react';
import React from 'react';
import type { OutputRootsItem } from 'types/api/outputRoots';
import { default as Thead } from 'ui/shared/TheadSticky';
import OutputRootsTableItem from './OutputRootsTableItem';
type Props = {
items: Array<OutputRootsItem>;
top: number;
}
const OutputRootsTable = ({ items, top }: Props) => {
return (
<Table variant="simple" size="sm">
<Thead top={ top }>
<Tr>
<Th width="130px">L2 output index</Th>
<Th width="120px">Age</Th>
<Th width="15%">L2 block #</Th>
<Th width="45%">L1 txn hash</Th>
<Th width="35%">Output root</Th>
</Tr>
</Thead>
<Tbody>
{ items.map((item) => (
<OutputRootsTableItem key={ item.l2_output_index } { ...item }/>
)) }
</Tbody>
</Table>
);
};
export default OutputRootsTable;
/* eslint-disable @typescript-eslint/naming-convention */
import { Box, Flex, Td, Tr, Text, Icon } from '@chakra-ui/react';
import React from 'react';
import type { OutputRootsItem } from 'types/api/outputRoots';
import appConfig from 'configs/app/config';
import txIcon from 'icons/transactions.svg';
import txBatchIcon from 'icons/txBatch.svg';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import link from 'lib/link/link';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal';
type Props = OutputRootsItem;
const OutputRootsTableItem = ({
l2_output_index,
l1_timestamp,
l2_block_number,
l1_tx_hash,
output_root,
}: Props) => {
const url = link('tx', { id: l1_tx_hash }, {}, appConfig.l1BaseUrl);
const timeAgo = useTimeAgoIncrement(l1_timestamp, false);
return (
<Tr>
<Td verticalAlign="middle">
<Text>{ l2_output_index }</Text>
</Td>
<Td verticalAlign="middle">
<Text variant="secondary">{ timeAgo }</Text>
</Td>
<Td verticalAlign="middle">
<LinkInternal fontWeight={ 600 } display="flex" alignItems="center" href={ link('block', { id: l2_block_number.toString() }) }>
<Icon as={ txBatchIcon } boxSize={ 6 } mr={ 1 }/>
{ l2_block_number }
</LinkInternal>
</Td>
<Td verticalAlign="middle" pr={ 12 }>
<Flex>
<LinkExternal href={ url } w="100%">
<Icon as={ txIcon } boxSize={ 6 } mr={ 1 }/>
<Box w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap"><HashStringShortenDynamic hash={ l1_tx_hash }/></Box>
</LinkExternal>
</Flex>
</Td>
<Td verticalAlign="middle">
<Flex overflow="hidden" whiteSpace="nowrap" w="100%" alignItems="center">
<Box w="calc(100% - 36px)"><HashStringShortenDynamic hash={ output_root }/></Box>
<CopyToClipboard text={ output_root } ml={ 2 }/>
</Flex>
</Td>
</Tr>
);
};
export default OutputRootsTableItem;
import { Flex, Hide, Show, Skeleton, Text } from '@chakra-ui/react';
import React from 'react';
import dataMock from 'data/outputRoots.json';
import isBrowser from 'lib/isBrowser';
import OutputRootsListItem from 'ui/outputRoots/OutputRootsListItem';
import OutputRootsTable from 'ui/outputRoots/OutputRootsTable';
import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
const OutputRoots = () => {
// request!!
const [ isLoading, setIsLoading ] = React.useState(true);
React.useEffect(() => {
if (isBrowser()) {
setTimeout(() => setIsLoading(false), 2000);
}
}, []);
const data = dataMock;
const isPaginationVisible = false;
const content = (() => {
if (isLoading) {
return (
<>
<SkeletonList display={{ base: 'block', lg: 'none' }}/>
<SkeletonTable display={{ base: 'none', lg: 'block' }} columns={ [ '130px', '120px', '15%', '45%', '35%' ] }/>
</>
);
}
return (
<>
<Show below="lg" ssr={ false }>{ data.items.map((item => <OutputRootsListItem key={ item.l2_output_index } { ...item }/>)) }</Show>
<Hide below="lg" ssr={ false }><OutputRootsTable items={ data.items } top={ isPaginationVisible ? 80 : 0 }/></Hide>
</>
);
})();
return (
<Page>
<PageTitle text="Output roots" withTextAd/>
{ isLoading ? <Skeleton w="400px" h="26px" mb={ 7 }/> : (
<Flex mb={ 7 } flexWrap="wrap">
L2 output index
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[0].l2_output_index } </Text>to
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[dataMock.items.length - 1].l2_output_index } </Text>
(total of { data.total.toLocaleString('en') } roots)
</Flex>
) }
{ /* Pagination */ }
{ content }
</Page>
);
};
export default OutputRoots;
...@@ -46,7 +46,7 @@ const TransactionPageContent = () => { ...@@ -46,7 +46,7 @@ const TransactionPageContent = () => {
.filter((explorer) => explorer.paths.tx) .filter((explorer) => explorer.paths.tx)
.map((explorer) => { .map((explorer) => {
const url = new URL(explorer.paths.tx + '/' + hash, explorer.baseUrl); const url = new URL(explorer.paths.tx + '/' + hash, explorer.baseUrl);
return <LinkExternal key={ explorer.baseUrl } href={ url.toString() }>{ `Open in ${ explorer.title }` }</LinkExternal>; return <LinkExternal key={ explorer.baseUrl } href={ url.toString() }>Open in { explorer.title }</LinkExternal>;
}); });
const additionals = ( const additionals = (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment