Commit 7fee6df6 authored by tom goriunov's avatar tom goriunov Committed by GitHub

update page titles (#1065)

* metadata helpers and values for txs pages

* update titles to the rest of the pages

* refactor getServerSideProps

* dynamically update metadata for token and dapp page

* test

* 404 error page
parent 5d98955a
......@@ -14,6 +14,10 @@ import 'lib/setLocale';
const PAGE_PROPS = {
cookies: '',
referrer: '',
id: '',
height_or_hash: '',
hash: '',
q: '',
};
const TestApp = ({ children }: {children: React.ReactNode}) => {
......
......@@ -7,7 +7,14 @@ type Props = {
pageProps: PageProps;
}
const AppContext = createContext<PageProps>({ cookies: '', referrer: '' });
const AppContext = createContext<PageProps>({
cookies: '',
referrer: '',
id: '',
height_or_hash: '',
hash: '',
q: '',
});
export function AppContextProvider({ children, pageProps }: Props) {
return (
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`generates correct metadata for: dynamic route 1`] = `
{
"description": "View transaction 0x12345 on Blockscout (Blockscout) Explorer",
"title": "Blockscout transaction 0x12345 | Blockscout",
}
`;
exports[`generates correct metadata for: dynamic route with API data 1`] = `
{
"description": "0x12345, balances and analytics on the Blockscout (Blockscout) Explorer",
"title": "Blockscout USDT token details | Blockscout",
}
`;
exports[`generates correct metadata for: static route 1`] = `
{
"description": "Blockscout is the #1 open-source blockchain explorer available today. 100+ chains and counting rely on Blockscout data availability, APIs, and ecosystem tools to support their networks.",
"title": "Blockscout blocks | Blockscout",
}
`;
export default function compileValue(template: string, params: Record<string, string | Array<string> | undefined>) {
const PLACEHOLDER_REGEX = /%(\w+)%/g;
return template.replaceAll(PLACEHOLDER_REGEX, (match, p1) => {
const value = params[p1];
if (Array.isArray(value)) {
return value.join(', ');
}
if (value === undefined) {
return '';
}
return value;
});
}
import type { Route } from 'nextjs-routes';
import type { ApiData } from './types';
import generate from './generate';
interface TestCase<R extends Route> {
title: string;
route: R;
apiData?: ApiData<R>;
}
const TEST_CASES: Array<TestCase<Route>> = [
{
title: 'static route',
route: {
pathname: '/blocks',
},
},
{
title: 'dynamic route',
route: {
pathname: '/tx/[hash]',
query: { hash: '0x12345' },
},
},
{
title: 'dynamic route with API data',
route: {
pathname: '/token/[hash]',
query: { hash: '0x12345' },
},
apiData: { symbol: 'USDT' },
} as TestCase<{ pathname: '/token/[hash]'; query: { hash: string }}>,
];
describe('generates correct metadata for:', () => {
TEST_CASES.forEach((testCase) => {
it(`${ testCase.title }`, () => {
const result = generate(testCase.route, testCase.apiData);
expect(result).toMatchSnapshot();
});
});
});
import type { Route } from 'nextjs-routes';
import type { ApiData, Metadata } from './types';
import appConfig from 'configs/app/config';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import compileValue from './compileValue';
import * as templates from './templates';
export default function generate<R extends Route>(route: R, apiData?: ApiData<R>): Metadata {
const params = {
...route.query,
...apiData,
network_name: appConfig.network.name,
network_title: getNetworkTitle(),
};
const title = compileValue(templates.title.make(route.pathname), params);
const description = compileValue(templates.description.make(route.pathname), params);
return {
title,
description,
};
}
export { default as generate } from './generate';
export { default as update } from './update';
import type { Route } from 'nextjs-routes';
// equal og:description
// eslint-disable-next-line max-len
const DEFAULT_TEMPLATE = 'Blockscout is the #1 open-source blockchain explorer available today. 100+ chains and counting rely on Blockscout data availability, APIs, and ecosystem tools to support their networks.';
// FIXME all page descriptions will be updated later
const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/': DEFAULT_TEMPLATE,
'/txs': DEFAULT_TEMPLATE,
'/tx/[hash]': 'View transaction %hash% on %network_title%',
'/blocks': DEFAULT_TEMPLATE,
'/block/[height_or_hash]': 'View the transactions, token transfers, and uncles for block %height_or_hash%',
'/accounts': DEFAULT_TEMPLATE,
'/address/[hash]': 'View the account balance, transactions, and other data for %hash% on the %network_title%',
'/verified-contracts': DEFAULT_TEMPLATE,
'/address/[hash]/contract-verification': 'View the account balance, transactions, and other data for %hash% on the %network_title%',
'/tokens': DEFAULT_TEMPLATE,
'/token/[hash]': '%hash%, balances and analytics on the %network_title%',
'/token/[hash]/instance/[id]': '%hash%, balances and analytics on the %network_title%',
'/apps': DEFAULT_TEMPLATE,
'/apps/[id]': DEFAULT_TEMPLATE,
'/stats': DEFAULT_TEMPLATE,
'/api-docs': DEFAULT_TEMPLATE,
'/graphiql': DEFAULT_TEMPLATE,
'/search-results': DEFAULT_TEMPLATE,
'/auth/profile': DEFAULT_TEMPLATE,
'/account/watchlist': DEFAULT_TEMPLATE,
'/account/api-key': DEFAULT_TEMPLATE,
'/account/custom-abi': DEFAULT_TEMPLATE,
'/account/public-tags-request': DEFAULT_TEMPLATE,
'/account/tag-address': DEFAULT_TEMPLATE,
'/account/verified-addresses': DEFAULT_TEMPLATE,
'/withdrawals': DEFAULT_TEMPLATE,
'/visualize/sol2uml': DEFAULT_TEMPLATE,
'/csv-export': DEFAULT_TEMPLATE,
'/l2-deposits': DEFAULT_TEMPLATE,
'/l2-output-roots': DEFAULT_TEMPLATE,
'/l2-txn-batches': DEFAULT_TEMPLATE,
'/l2-withdrawals': DEFAULT_TEMPLATE,
'/404': DEFAULT_TEMPLATE,
// service routes, added only to make typescript happy
'/login': DEFAULT_TEMPLATE,
'/api/media-type': DEFAULT_TEMPLATE,
'/api/proxy': DEFAULT_TEMPLATE,
'/api/csrf': DEFAULT_TEMPLATE,
'/api/healthz': DEFAULT_TEMPLATE,
'/auth/auth0': DEFAULT_TEMPLATE,
'/auth/unverified-email': DEFAULT_TEMPLATE,
};
export function make(pathname: Route['pathname']) {
const template = TEMPLATE_MAP[pathname];
return template ?? '';
}
export * as title from './title';
export * as description from './description';
import type { Route } from 'nextjs-routes';
const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/': 'blockchain explorer',
'/txs': 'transactions',
'/tx/[hash]': 'transaction %hash%',
'/blocks': 'blocks',
'/block/[height_or_hash]': 'block %height_or_hash%',
'/accounts': 'top accounts',
'/address/[hash]': 'address details for %hash%',
'/verified-contracts': 'verified contracts',
'/address/[hash]/contract-verification': 'contract verification for %hash%',
'/tokens': 'tokens',
'/token/[hash]': '%symbol% token details',
'/token/[hash]/instance/[id]': 'token instance for %symbol%',
'/apps': 'apps marketplace',
'/apps/[id]': '- %app_name%',
'/stats': 'statistics',
'/api-docs': 'REST API',
'/graphiql': 'GraphQL',
'/search-results': 'search result for %q%',
'/auth/profile': '- my profile',
'/account/watchlist': '- watchlist',
'/account/api-key': '- API keys',
'/account/custom-abi': '- custom ABI',
'/account/public-tags-request': '- public tag requests',
'/account/tag-address': '- private tags',
'/account/verified-addresses': '- my verified addresses',
'/withdrawals': 'withdrawals',
'/visualize/sol2uml': 'Solidity UML diagram',
'/csv-export': 'export data to CSV',
'/l2-deposits': 'deposits (L1 > L2)',
'/l2-output-roots': 'output roots',
'/l2-txn-batches': 'Tx batches (L2 blocks)',
'/l2-withdrawals': 'withdrawals (L2 > L1)',
'/404': 'error - page not found',
// service routes, added only to make typescript happy
'/login': 'login',
'/api/media-type': 'node API media type',
'/api/proxy': 'node API proxy',
'/api/csrf': 'node API CSRF token',
'/api/healthz': 'node API health check',
'/auth/auth0': 'authentication',
'/auth/unverified-email': 'unverified email',
};
export function make(pathname: Route['pathname']) {
const template = TEMPLATE_MAP[pathname];
return `%network_name% ${ template } | Blockscout`;
}
import type { Route } from 'nextjs-routes';
/* eslint-disable @typescript-eslint/indent */
export type ApiData<R extends Route> =
R['pathname'] extends '/token/[hash]' ? { symbol: string } :
R['pathname'] extends '/token/[hash]/instance/[id]' ? { symbol: string } :
R['pathname'] extends '/apps/[id]' ? { app_name: string } :
never;
export interface Metadata {
title: string;
description: string;
}
import type { Route } from 'nextjs-routes';
import type { ApiData } from './types';
import generate from './generate';
export default function update<R extends Route>(route: R, apiData: ApiData<R>) {
const { title, description } = generate(route, apiData);
window.document.title = title;
window.document.querySelector('meta[name="description"]')?.setAttribute('content', description);
}
......@@ -33,6 +33,7 @@ const PAGE_TYPE_DICT: Record<Route['pathname'], string> = {
'/l2-output-roots': 'Output roots',
'/l2-txn-batches': 'Tx batches (L2 blocks)',
'/l2-withdrawals': 'Withdrawals (L2 > L1)',
'/404': '404',
// service routes, added only to make typescript happy
'/login': 'Login',
......@@ -41,7 +42,7 @@ const PAGE_TYPE_DICT: Record<Route['pathname'], string> = {
'/api/csrf': 'Node API: CSRF token',
'/api/healthz': 'Node API: Health check',
'/auth/auth0': 'Auth',
'/auth/unverified-email': 'Auth',
'/auth/unverified-email': 'Unverified email',
};
export default function getPageType(pathname: Route['pathname']) {
......
import appConfig from 'configs/app/config';
// TODO delete when page descriptions is refactored
export default function getNetworkTitle() {
return appConfig.network.name + (appConfig.network.shortName ? ` (${ appConfig.network.shortName })` : '') + ' Explorer';
}
import Head from 'next/head';
import type { Route } from 'nextjs-routes';
import React from 'react';
import * as metadata from 'lib/metadata';
type Props = Route & {
children: React.ReactNode;
}
const PageServer = (props: Props) => {
const { title, description } = metadata.generate(props);
return (
<>
<Head>
<title>{ title }</title>
<meta name="description" content={ description }/>
</Head>
{ props.children }
</>
);
};
export default React.memo(PageServer);
import appConfig from 'configs/app/config';
import { getServerSideProps as base } from '../getServerSideProps';
export const getServerSideProps: typeof base = async(...args) => {
if (!appConfig.account.isEnabled) {
return {
notFound: true,
};
}
return base(...args);
};
export const getServerSidePropsForVerifiedAddresses: typeof base = async(...args) => {
if (!appConfig.account.isEnabled || !appConfig.adminServiceApi.endpoint || !appConfig.contractInfoApi.endpoint) {
return {
notFound: true,
};
}
return base(...args);
};
import type { RoutedQuery } from 'nextjs-routes';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
export default function getSeo(params: RoutedQuery<'/address/[hash]'>) {
const networkTitle = getNetworkTitle();
return {
title: params ? `${ params.hash } - ${ networkTitle }` : '',
description: params ?
`View the account balance, transactions, and other data for ${ params.hash } on the ${ networkTitle }` :
'',
};
}
import type { RoutedQuery } from 'nextjs-routes';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
export default function getSeo(params?: RoutedQuery<'/block/[height_or_hash]'>) {
const networkTitle = getNetworkTitle();
const isHash = params ? params.height_or_hash.startsWith('0x') : false;
return {
title: params ? `Block ${ params.height_or_hash } - ${ networkTitle }` : '',
description: params ?
`View the transactions, token transfers, and uncles for block ${ isHash ? '' : 'number ' }${ params.height_or_hash }` : '',
};
}
import getNetworkTitle from 'lib/networks/getNetworkTitle';
export default function getSeo() {
return {
title: getNetworkTitle(),
};
}
import type { GetServerSideProps } from 'next';
import appConfig from 'configs/app/config';
export type Props = {
cookies: string;
referrer: string;
id?: string;
height?: string;
hash?: string;
id: string;
height_or_hash: string;
hash: string;
q: string;
}
export const getServerSideProps: GetServerSideProps<Props> = async({ req, query }) => {
export const base: GetServerSideProps<Props> = async({ req, query }) => {
return {
props: {
cookies: req.headers.cookie || '',
......@@ -16,6 +19,87 @@ export const getServerSideProps: GetServerSideProps<Props> = async({ req, query
id: query.id?.toString() || '',
hash: query.hash?.toString() || '',
height_or_hash: query.height_or_hash?.toString() || '',
q: query.q?.toString() || '',
},
};
};
export const account: GetServerSideProps<Props> = async(context) => {
if (!appConfig.account.isEnabled) {
return {
notFound: true,
};
}
return base(context);
};
export const verifiedAddresses: GetServerSideProps<Props> = async(context) => {
if (!appConfig.adminServiceApi.endpoint || !appConfig.contractInfoApi.endpoint) {
return {
notFound: true,
};
}
return account(context);
};
export const beaconChain: GetServerSideProps<Props> = async(context) => {
if (!appConfig.beaconChain.hasBeaconChain) {
return {
notFound: true,
};
}
return base(context);
};
export const L2: GetServerSideProps<Props> = async(context) => {
if (!appConfig.L2.isL2Network) {
return {
notFound: true,
};
}
return base(context);
};
export const marketplace: GetServerSideProps<Props> = async(context) => {
if (!appConfig.marketplace.configUrl || !appConfig.network.rpcUrl) {
return {
notFound: true,
};
}
return base(context);
};
export const apiDocs: GetServerSideProps<Props> = async(context) => {
if (!appConfig.apiDoc.specUrl) {
return {
notFound: true,
};
}
return base(context);
};
export const csvExport: GetServerSideProps<Props> = async(context) => {
if (!appConfig.reCaptcha.siteKey) {
return {
notFound: true,
};
}
return base(context);
};
export const stats: GetServerSideProps<Props> = async(context) => {
if (!appConfig.statsApi.endpoint) {
return {
notFound: true,
};
}
return base(context);
};
import type { GetServerSideProps } from 'next';
import appConfig from 'configs/app/config';
import type { Props } from 'lib/next/getServerSideProps';
import { getServerSideProps as getServerSidePropsBase } from 'lib/next/getServerSideProps';
export const getServerSideProps: GetServerSideProps<Props> = async(args) => {
if (!appConfig.beaconChain.hasBeaconChain) {
return {
notFound: true,
};
}
return getServerSidePropsBase(args);
};
import type { GetServerSideProps } from 'next';
import appConfig from 'configs/app/config';
import type { Props } from 'lib/next/getServerSideProps';
import { getServerSideProps as getServerSidePropsBase } from 'lib/next/getServerSideProps';
export const getServerSideProps: GetServerSideProps<Props> = async(args) => {
if (!appConfig.L2.isL2Network) {
return {
notFound: true,
};
}
return getServerSidePropsBase(args);
};
import type { PageParams } from './types';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
export default function getSeo(params: PageParams) {
const networkTitle = getNetworkTitle();
return {
title: params ? `${ params.hash } - ${ networkTitle }` : '',
description: params ?
`${ params.hash }, balances and analytics on the ${ networkTitle }` :
'',
};
}
import type { GetServerSideProps, GetServerSidePropsResult } from 'next';
export type Props = {
cookies: string;
referrer: string;
hash?: string;
}
export const getServerSideProps: GetServerSideProps = async({ req, query }): Promise<GetServerSidePropsResult<Props>> => {
return {
props: {
cookies: req.headers.cookie || '',
referrer: req.headers.referer || '',
hash: query.hash?.toString() || '',
},
};
};
export type PageParams = {
hash: string;
}
import type { RoutedQuery } from 'nextjs-routes';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
export default function getSeo(params?: RoutedQuery<'/tx/[hash]'>) {
const networkTitle = getNetworkTitle();
return {
title: params ? `Transaction ${ params.hash } - ${ networkTitle }` : '',
description: params ? `View transaction ${ params.hash } on ${ networkTitle }` : '',
};
}
import React from 'react';
import PageServer from 'lib/next/PageServer';
import AppError from 'ui/shared/AppError/AppError';
import Page from 'ui/shared/Page/Page';
const Custom404 = () => {
return (
<PageServer pathname="/404">
<Page>
<AppError statusCode={ 404 } mt="50px"/>
</Page>
</PageServer>
);
};
export default Custom404;
......@@ -19,37 +19,18 @@
import * as Sentry from '@sentry/nextjs';
import type { GetServerSideProps } from 'next';
import NextErrorComponent from 'next/error';
import Head from 'next/head';
import React from 'react';
import sentryConfig from 'configs/sentry/nextjs';
import * as cookies from 'lib/cookies';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import type { Props as ServerSidePropsCommon } from 'lib/next/getServerSideProps';
import { getServerSideProps as getServerSidePropsCommon } from 'lib/next/getServerSideProps';
import AppError from 'ui/shared/AppError/AppError';
import Page from 'ui/shared/Page/Page';
import { base as getServerSidePropsCommon } from 'lib/next/getServerSideProps';
type Props = ServerSidePropsCommon & {
statusCode: number;
}
const CustomErrorComponent = (props: Props) => {
if (props.statusCode === 404) {
const title = getNetworkTitle();
return (
<>
<Head>
<title>{ title }</title>
</Head>
<Page>
<AppError statusCode={ 404 } mt="50px"/>
</Page>
</>
);
}
const colorModeCookie = cookies.getFromCookieString(props.cookies || '', cookies.NAMES.COLOR_MODE);
return <NextErrorComponent statusCode={ props.statusCode } withDarkMode={ colorModeCookie === 'dark' }/>;
};
......
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const ApiKeys = dynamic(() => import('ui/pages/ApiKeys'), { ssr: false });
const ApiKeysPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head><title>{ title }</title></Head>
<PageServer pathname="/account/api-key">
<Page>
<ApiKeys/>
</Page>
</>
</PageServer>
);
};
export default ApiKeysPage;
export { getServerSideProps } from 'lib/next/account/getServerSideProps';
export { account as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const CustomAbi = dynamic(() => import('ui/pages/CustomAbi'), { ssr: false });
const CustomAbiPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head><title>{ title }</title></Head>
<PageServer pathname="/account/custom-abi">
<Page>
<CustomAbi/>
</Page>
</>
</PageServer>
);
};
export default CustomAbiPage;
export { getServerSideProps } from 'lib/next/account/getServerSideProps';
export { account as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const PublicTags = dynamic(() => import('ui/pages/PublicTags'), { ssr: false });
const PublicTagsPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head><title>{ title }</title></Head>
<PageServer pathname="/account/public-tags-request">
<Page>
<PublicTags/>
</Page>
</>
</PageServer>
);
};
export default PublicTagsPage;
export { getServerSideProps } from 'lib/next/account/getServerSideProps';
export { account as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const PrivateTags = dynamic(() => import('ui/pages/PrivateTags'), { ssr: false });
const PrivateTagsPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head><title>{ title }</title></Head>
<PageServer pathname="/account/tag-address">
<Page>
<PrivateTags/>
</Page>
</>
</PageServer>
);
};
export default PrivateTagsPage;
export { getServerSideProps } from 'lib/next/account/getServerSideProps';
export { account as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const VerifiedAddresses = dynamic(() => import('ui/pages/VerifiedAddresses'), { ssr: false });
const VerifiedAddressesPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head><title>{ title }</title></Head>
<PageServer pathname="/account/verified-addresses">
<Page>
<VerifiedAddresses/>
</Page>
</>
</PageServer>
);
};
export default VerifiedAddressesPage;
export { getServerSidePropsForVerifiedAddresses as getServerSideProps } from 'lib/next/account/getServerSideProps';
export { verifiedAddresses as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const WatchList = dynamic(() => import('ui/pages/Watchlist'), { ssr: false });
const WatchListPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head>
<title>{ title }</title>
</Head>
<PageServer pathname="/account/watchlist">
<Page>
<WatchList/>
</Page>
</>
</PageServer>
);
};
export default WatchListPage;
export { getServerSideProps } from 'lib/next/account/getServerSideProps';
export { account as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const Accounts = dynamic(() => import('ui/pages/Accounts'), { ssr: false });
const AccountsPage: NextPage = () => {
const title = `Top Accounts - ${ getNetworkTitle() }`;
return (
<>
<Head><title>{ title }</title></Head>
<PageServer pathname="/accounts">
<Page>
<Accounts/>
</Page>
</>
</PageServer>
);
};
export default AccountsPage;
export { getServerSideProps } from 'lib/next/getServerSideProps';
export { base as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import Head from 'next/head';
import type { RoutedQuery } from 'nextjs-routes';
import React from 'react';
import getSeo from 'lib/next/address/getSeo';
import type { Props } from 'lib/next/getServerSideProps';
import PageServer from 'lib/next/PageServer';
import ContractVerification from 'ui/pages/ContractVerification';
import Page from 'ui/shared/Page/Page';
const ContractVerificationPage: NextPage<RoutedQuery<'/address/[hash]/contract-verification'>> =
({ hash }: RoutedQuery<'/address/[hash]/contract-verification'>) => {
const { title, description } = getSeo({ hash });
const ContractVerificationPage: NextPage<Props> = (props: Props) => {
return (
<>
<Head>
<title>{ title }</title>
<meta name="description" content={ description }/>
</Head>
<PageServer pathname="/address/[hash]/contract-verification" query={ props }>
<Page>
<ContractVerification/>
</Page>
</>
</PageServer>
);
};
export default ContractVerificationPage;
export { getServerSideProps } from 'lib/next/getServerSideProps';
export { base as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import type { RoutedQuery } from 'nextjs-routes';
import React from 'react';
import getSeo from 'lib/next/address/getSeo';
import type { Props } from 'lib/next/getServerSideProps';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const Address = dynamic(() => import('ui/pages/Address'), { ssr: false });
const AddressPage: NextPage<RoutedQuery<'/address/[hash]'>> = ({ hash }: RoutedQuery<'/address/[hash]'>) => {
const { title, description } = getSeo({ hash });
const AddressPage: NextPage<Props> = (props: Props) => {
return (
<>
<Head>
<title>{ title }</title>
<meta name="description" content={ description }/>
</Head>
<PageServer pathname="/address/[hash]" query={ props }>
<Page>
<Address/>
</Page>
</>
</PageServer>
);
};
export default AddressPage;
export { getServerSideProps } from 'lib/next/getServerSideProps';
export { base as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage, GetServerSideProps } from 'next';
import Head from 'next/head';
import type { NextPage } from 'next';
import React from 'react';
import appConfig from 'configs/app/config';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import { getServerSideProps as getServerSidePropsBase } from 'lib/next/getServerSideProps';
import type { Props } from 'lib/next/getServerSideProps';
import PageServer from 'lib/next/PageServer';
import SwaggerUI from 'ui/apiDocs/SwaggerUI';
import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle';
const APIDocsPage: NextPage = () => {
const networkTitle = getNetworkTitle();
return (
<Page>
<PageTitle title="API Documentation"/>
<Head><title>{ `API for the ${ networkTitle }` }</title></Head>
<SwaggerUI/>
</Page>
<PageServer pathname="/api-docs">
<Page>
<PageTitle title="API Documentation"/>
<SwaggerUI/>
</Page>
</PageServer>
);
};
export default APIDocsPage;
export const getServerSideProps: GetServerSideProps<Props> = async(args) => {
if (!appConfig.apiDoc.specUrl) {
return {
notFound: true,
};
}
return getServerSidePropsBase(args);
};
export { apiDocs as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage, GetServerSideProps } from 'next';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import appConfig from 'configs/app/config';
import type { Props } from 'lib/next/getServerSideProps';
import { getServerSideProps as getServerSidePropsBase } from 'lib/next/getServerSideProps';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const MarketplaceApp = dynamic(() => import('ui/pages/MarketplaceApp'), { ssr: false });
const MarketplaceAppPage: NextPage = () => {
const MarketplaceAppPage: NextPage<Props> = (props: Props) => {
return (
<>
<Head><title>Blockscout | Marketplace</title></Head>
<PageServer pathname="/apps/[id]" query={ props }>
<Page wrapChildren={ false }>
<MarketplaceApp/>
</Page>
</>
</PageServer>
);
};
export default MarketplaceAppPage;
export const getServerSideProps: GetServerSideProps<Props> = async(args) => {
if (!appConfig.marketplace.configUrl || !appConfig.network.rpcUrl) {
return {
notFound: true,
};
}
return getServerSidePropsBase(args);
};
export { marketplace as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage, GetServerSideProps } from 'next';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import appConfig from 'configs/app/config';
import type { Props } from 'lib/next/getServerSideProps';
import { getServerSideProps as getServerSidePropsBase } from 'lib/next/getServerSideProps';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle';
......@@ -13,24 +10,15 @@ const Marketplace = dynamic(() => import('ui/pages/Marketplace'), { ssr: false }
const MarketplacePage: NextPage = () => {
return (
<>
<Head><title>Blockscout | Marketplace</title></Head>
<PageServer pathname="/apps">
<Page>
<PageTitle title="Marketplace"/>
<Marketplace/>
</Page>
</>
</PageServer>
);
};
export default MarketplacePage;
export const getServerSideProps: GetServerSideProps<Props> = async(args) => {
if (!appConfig.marketplace.configUrl || !appConfig.network.rpcUrl) {
return {
notFound: true,
};
}
return getServerSidePropsBase(args);
};
export { marketplace as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import Head from 'next/head';
import React from 'react';
import PageServer from 'lib/next/PageServer';
import MyProfile from 'ui/pages/MyProfile';
import Page from 'ui/shared/Page/Page';
const MyProfilePage: NextPage = () => {
return (
<>
<Head><title>My profile</title></Head>
<PageServer pathname="/auth/profile">
<Page>
<MyProfile/>
</Page>
</>
</PageServer>
);
};
export default MyProfilePage;
export { getServerSideProps } from 'lib/next/account/getServerSideProps';
export { account as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PageServer from 'lib/next/PageServer';
import UnverifiedEmail from 'ui/pages/UnverifiedEmail';
import Page from 'ui/shared/Page/Page';
const UnverifiedEmailPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head><title>{ title }</title></Head>
<PageServer pathname="/auth/unverified-email">
<Page>
<UnverifiedEmail/>
</Page>
</>
</PageServer>
);
};
export default UnverifiedEmailPage;
export { getServerSideProps } from 'lib/next/account/getServerSideProps';
export { account as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import type { RoutedQuery } from 'nextjs-routes';
import React from 'react';
import getSeo from 'lib/next/block/getSeo';
import type { Props } from 'lib/next/getServerSideProps';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const Block = dynamic(() => import('ui/pages/Block'), { ssr: false });
const BlockPage: NextPage<RoutedQuery<'/block/[height_or_hash]'>> = (params: RoutedQuery<'/block/[height_or_hash]'>) => {
const { title, description } = getSeo({ height_or_hash: params.height_or_hash });
const BlockPage: NextPage<Props> = (props: Props) => {
return (
<>
<Head>
<title>{ title }</title>
<meta name="description" content={ description }/>
</Head>
<PageServer pathname="/block/[height_or_hash]" query={ props }>
<Page>
<Block/>
</Page>
</>
</PageServer>
);
};
export default BlockPage;
export { getServerSideProps } from 'lib/next/getServerSideProps';
export { base as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import getSeo from 'lib/next/blocks/getSeo';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const Blocks = dynamic(() => import('ui/pages/Blocks'), { ssr: false });
const BlockPage: NextPage = () => {
const { title } = getSeo();
return (
<>
<Head>
<title>{ title }</title>
</Head>
<PageServer pathname="/blocks">
<Page>
<Blocks/>
</Page>
</>
</PageServer>
);
};
export default BlockPage;
export { getServerSideProps } from 'lib/next/getServerSideProps';
export { base as getServerSideProps } from 'lib/next/getServerSideProps';
import type { GetServerSideProps, NextPage } from 'next';
import Head from 'next/head';
import type { NextPage } from 'next';
import React from 'react';
import appConfig from 'configs/app/config';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import type { Props } from 'lib/next/getServerSideProps';
import { getServerSideProps as getServerSidePropsBase } from 'lib/next/getServerSideProps';
import PageServer from 'lib/next/PageServer';
import CsvExport from 'ui/pages/CsvExport';
const CsvExportPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head>
<title>{ title }</title>
</Head>
<PageServer pathname="/csv-export">
<CsvExport/>
</>
</PageServer>
);
};
export default CsvExportPage;
export const getServerSideProps: GetServerSideProps<Props> = async(args) => {
if (!appConfig.reCaptcha.siteKey) {
return {
notFound: true,
};
}
return getServerSidePropsBase(args);
};
export { csvExport as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
const GraphQL = dynamic(() => import('ui/graphQL/GraphQL'), {
loading: () => <ContentLoader/>,
ssr: false,
});
import Head from 'next/head';
import React from 'react';
import PageServer from 'lib/next/PageServer';
import ContentLoader from 'ui/shared/ContentLoader';
import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle';
const GraphQL = dynamic(() => import('ui/graphQL/GraphQL'), {
loading: () => <ContentLoader/>,
ssr: false,
});
const GraphiqlPage: NextPage = () => {
return (
<Page>
<Head><title>Graph Page</title></Head>
<PageTitle title="GraphQL playground"/>
<GraphQL/>
</Page>
<PageServer pathname="/graphiql">
<Page>
<PageTitle title="GraphQL playground"/>
<GraphQL/>
</Page>
</PageServer>
);
};
export default GraphiqlPage;
export { getServerSideProps } from 'lib/next/getServerSideProps';
export { base as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import Head from 'next/head';
import React from 'react';
import PageServer from 'lib/next/PageServer';
import Home from 'ui/pages/Home';
const HomePage: NextPage = () => {
return (
<>
<Head><title>Home Page</title></Head>
<PageServer pathname="/">
<Home/>
</>
</PageServer>
);
};
export default HomePage;
export { getServerSideProps } from 'lib/next/getServerSideProps';
export { base as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const L2Deposits = dynamic(() => import('ui/pages/L2Deposits'), { ssr: false });
const DepositsPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head>
<title>{ title }</title>
</Head>
<PageServer pathname="/l2-deposits">
<Page>
<L2Deposits/>
</Page>
</>
</PageServer>
);
};
export default DepositsPage;
export { getServerSideProps } from 'lib/next/getServerSidePropsL2';
export { L2 as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const L2OutputRoots = dynamic(() => import('ui/pages/L2OutputRoots'), { ssr: false });
const OutputRootsPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head>
<title>{ title }</title>
</Head>
<PageServer pathname="/l2-output-roots">
<Page>
<L2OutputRoots/>
</Page>
</>
</PageServer>
);
};
export default OutputRootsPage;
export { getServerSideProps } from 'lib/next/getServerSidePropsL2';
export { L2 as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const L2TxnBatches = dynamic(() => import('ui/pages/L2TxnBatches'), { ssr: false });
const TxnBatchesPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head>
<title>{ title }</title>
</Head>
<PageServer pathname="/l2-txn-batches">
<Page>
<L2TxnBatches/>
</Page>
</>
</PageServer>
);
};
export default TxnBatchesPage;
export { getServerSideProps } from 'lib/next/getServerSidePropsL2';
export { L2 as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const L2Withdrawals = dynamic(() => import('ui/pages/L2Withdrawals'), { ssr: false });
const WithdrawalsPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head>
<title>{ title }</title>
</Head>
<PageServer pathname="/l2-withdrawals">
<Page>
<L2Withdrawals/>
</Page>
</>
</PageServer>
);
};
export default WithdrawalsPage;
export { getServerSideProps } from 'lib/next/getServerSidePropsL2';
export { L2 as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import Head from 'next/head';
import React from 'react';
import PageServer from 'lib/next/PageServer';
import Login from 'ui/pages/Login';
const LoginPage: NextPage = () => {
return (
<>
<Head><title>Login Page</title></Head>
<PageServer pathname="/login">
<Login/>
</>
</PageServer>
);
};
export default LoginPage;
export { getServerSideProps } from 'lib/next/getServerSideProps';
export { base as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import type { Props } from 'lib/next/getServerSideProps';
import PageServer from 'lib/next/PageServer';
const SearchResults = dynamic(() => import('ui/pages/SearchResults'), { ssr: false });
const SearchResultsPage: NextPage = () => {
const title = getNetworkTitle();
const SearchResultsPage: NextPage<Props> = (props: Props) => {
return (
<>
<Head>
<title>{ title }</title>
</Head>
<PageServer pathname="/search-results" query={ props }>
<SearchResults/>
</>
</PageServer>
);
};
export default SearchResultsPage;
export { getServerSideProps } from 'lib/next/getServerSideProps';
export { base as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage, GetServerSideProps } from 'next';
import Head from 'next/head';
import type { NextPage } from 'next';
import React from 'react';
import appConfig from 'configs/app/config';
import type { Props } from 'lib/next/getServerSideProps';
import { getServerSideProps as getServerSidePropsBase } from 'lib/next/getServerSideProps';
import PageServer from 'lib/next/PageServer';
import Stats from '../ui/pages/Stats';
const StatsPage: NextPage = () => {
return (
<>
<Head><title>{ appConfig.network.name } stats</title></Head>
<PageServer pathname="/stats">
<Stats/>
</>
</PageServer>
);
};
export default StatsPage;
export const getServerSideProps: GetServerSideProps<Props> = async(args) => {
if (!appConfig.statsApi.endpoint) {
return {
notFound: true,
};
}
return getServerSidePropsBase(args);
};
export { stats as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import type { PageParams } from 'lib/next/token/types';
import getSeo from 'lib/next/token/getSeo';
import type { Props } from 'lib/next/getServerSideProps';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const Token = dynamic(() => import('ui/pages/Token'), { ssr: false });
const TokenPage: NextPage<PageParams> = ({ hash }: PageParams) => {
const { title, description } = getSeo({ hash });
const TokenPage: NextPage<Props> = (props: Props) => {
return (
<>
<Head>
<title>{ title }</title>
<meta name="description" content={ description }/>
</Head>
<PageServer pathname="/token/[hash]" query={ props }>
<Page>
<Token/>
</Page>
</>
</PageServer>
);
};
export default TokenPage;
export { getServerSideProps } from 'lib/next/token/getServerSideProps';
export { base as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import type { PageParams } from 'lib/next/token/types';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import type { Props } from 'lib/next/getServerSideProps';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const TokenInstance = dynamic(() => import('ui/pages/TokenInstance'), { ssr: false });
const TokenInstancePage: NextPage<PageParams> = () => {
const title = getNetworkTitle();
const TokenInstance = dynamic(() => import('ui/pages/TokenInstance'), { ssr: false });
const TokenInstancePage: NextPage<Props> = (props: Props) => {
return (
<>
<Head>
<title>{ title }</title>
</Head>
<PageServer pathname="/token/[hash]/instance/[id]" query={ props }>
<Page>
<TokenInstance/>
</Page>
</>
</PageServer>
);
};
export default TokenInstancePage;
export { getServerSideProps } from 'lib/next/token/getServerSideProps';
export { base as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const Tokens = dynamic(() => import('ui/pages/Tokens'), { ssr: false });
const TokensPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head>
<title>{ title }</title>
</Head>
<PageServer pathname="/tokens">
<Page>
<Tokens/>
</Page>
</>
</PageServer>
);
};
export default TokensPage;
export { getServerSideProps } from 'lib/next/getServerSideProps';
export { base as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import type { RoutedQuery } from 'nextjs-routes';
import React from 'react';
import getSeo from 'lib/next/tx/getSeo';
import type { Props } from 'lib/next/getServerSideProps';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const Transaction = dynamic(() => import('ui/pages/Transaction'), { ssr: false });
const TransactionPage: NextPage<RoutedQuery<'/tx/[hash]'>> = ({ hash }: RoutedQuery<'/tx/[hash]'>) => {
const { title, description } = getSeo({ hash });
const TransactionPage: NextPage<Props> = (props: Props) => {
return (
<>
<Head>
<title>{ title }</title>
<meta name="description" content={ description }/>
</Head>
<PageServer pathname="/tx/[hash]" query={ props }>
<Page>
<Transaction/>
</Page>
</>
</PageServer>
);
};
export default TransactionPage;
export { getServerSideProps } from 'lib/next/getServerSideProps';
export { base as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const Transactions = dynamic(() => import('ui/pages/Transactions'), { ssr: false });
const TxsPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head><title>{ title }</title></Head>
<PageServer pathname="/txs">
<Page>
<Transactions/>
</Page>
</>
</PageServer>
);
};
export default TxsPage;
export { getServerSideProps } from 'lib/next/getServerSideProps';
export { base as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const VerifiedContracts = dynamic(() => import('ui/pages/VerifiedContracts'), { ssr: false });
const VerifiedContractsPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head>
<title>{ title }</title>
</Head>
<PageServer pathname="/verified-contracts">
<Page>
<VerifiedContracts/>
</Page>
</>
</PageServer>
);
};
export default VerifiedContractsPage;
export { getServerSideProps } from 'lib/next/getServerSideProps';
export { base as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PageServer from 'lib/next/PageServer';
import Sol2Uml from 'ui/pages/Sol2Uml';
const Sol2UmlPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head>
<title>{ title }</title>
</Head>
<PageServer pathname="/visualize/sol2uml">
<Sol2Uml/>
</>
</PageServer>
);
};
export default Sol2UmlPage;
export { getServerSideProps } from 'lib/next/getServerSideProps';
export { base as getServerSideProps } from 'lib/next/getServerSideProps';
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import PageServer from 'lib/next/PageServer';
import Page from 'ui/shared/Page/Page';
const Withdrawals = dynamic(() => import('ui/pages/Withdrawals'), { ssr: false });
const WithdrawalsPage: NextPage = () => {
const title = getNetworkTitle();
return (
<>
<Head>
<title>{ title }</title>
</Head>
<PageServer pathname="/withdrawals">
<Page>
<Withdrawals/>
</Page>
</>
</PageServer>
);
};
export default WithdrawalsPage;
export { getServerSideProps } from 'lib/next/getServerSidePropsBeacon';
export { beaconChain as getServerSideProps } from 'lib/next/getServerSideProps';
......@@ -23,6 +23,10 @@ const defaultAppContext = {
pageProps: {
cookies: '',
referrer: '',
id: '',
height_or_hash: '',
hash: '',
q: '',
},
};
......
......@@ -6,6 +6,7 @@
// prettier-ignore
declare module "nextjs-routes" {
export type Route =
| StaticRoute<"/404">
| StaticRoute<"/account/api-key">
| StaticRoute<"/account/custom-abi">
| StaticRoute<"/account/public-tags-request">
......
......@@ -10,6 +10,7 @@ import appConfig from 'configs/app/config';
import type { ResourceError } from 'lib/api/resources';
import { useAppContext } from 'lib/contexts/app';
import useApiFetch from 'lib/hooks/useFetch';
import * as metadata from 'lib/metadata';
import getQueryParamString from 'lib/router/getQueryParamString';
import ContentLoader from 'ui/shared/ContentLoader';
import PageTitle from 'ui/shared/Page/PageTitle';
......@@ -70,6 +71,15 @@ const MarketplaceApp = () => {
}
}, [ isFrameLoading, data, colorMode, ref ]);
useEffect(() => {
if (data) {
metadata.update(
{ pathname: '/apps/[id]', query: { id: data.id } },
{ app_name: data.title },
);
}
}, [ data ]);
if (isError) {
throw new Error('Unable to load app', { cause: error });
}
......
......@@ -15,6 +15,7 @@ import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery';
import { useAppContext } from 'lib/contexts/app';
import useContractTabs from 'lib/hooks/useContractTabs';
import useIsMobile from 'lib/hooks/useIsMobile';
import * as metadata from 'lib/metadata';
import getQueryParamString from 'lib/router/getQueryParamString';
import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage';
......@@ -108,16 +109,7 @@ const TokenPageContent = () => {
useEffect(() => {
if (tokenQuery.data && !tokenQuery.isPlaceholderData) {
const tokenSymbol = tokenQuery.data.symbol ? ` (${ tokenQuery.data.symbol })` : '';
const tokenName = `${ tokenQuery.data.name || 'Unnamed' }${ tokenSymbol }`;
const title = document.getElementsByTagName('title')[0];
if (title) {
title.textContent = title.textContent?.replace(tokenQuery.data.address, tokenName) || title.textContent;
}
const description = document.getElementsByName('description')[0] as HTMLMetaElement;
if (description) {
description.content = description.content.replace(tokenQuery.data.address, tokenName) || description.content;
}
metadata.update({ pathname: '/token/[hash]', query: { hash: tokenQuery.data.address } }, { symbol: tokenQuery.data.symbol ?? '' });
}
}, [ tokenQuery.data, tokenQuery.isPlaceholderData ]);
......
......@@ -9,6 +9,7 @@ import nftIcon from 'icons/nft_shield.svg';
import useApiQuery from 'lib/api/useApiQuery';
import { useAppContext } from 'lib/contexts/app';
import useIsMobile from 'lib/hooks/useIsMobile';
import * as metadata from 'lib/metadata';
import * as regexp from 'lib/regexp';
import { TOKEN_INSTANCE } from 'stubs/token';
import * as tokenStubs from 'stubs/token';
......@@ -74,6 +75,15 @@ const TokenInstanceContent = () => {
},
});
React.useEffect(() => {
if (tokenInstanceQuery.data && !tokenInstanceQuery.isPlaceholderData) {
metadata.update(
{ pathname: '/token/[hash]/instance/[id]', query: { hash: tokenInstanceQuery.data.token.address, id: tokenInstanceQuery.data.id } },
{ symbol: tokenInstanceQuery.data.token.symbol ?? '' },
);
}
}, [ tokenInstanceQuery.data, tokenInstanceQuery.isPlaceholderData ]);
const backLink = React.useMemo(() => {
const hasGoBackLink = appProps.referrer && appProps.referrer.includes(`/token/${ hash }`) && !appProps.referrer.includes('instance');
......
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