Skip to content

Commit

Permalink
Production Release
Browse files Browse the repository at this point in the history
Production Release
  • Loading branch information
tcheee authored Oct 8, 2024
2 parents f92ab88 + 018e5bd commit bdde13d
Show file tree
Hide file tree
Showing 33 changed files with 4,632 additions and 143 deletions.
11 changes: 0 additions & 11 deletions next-sitemap.config.js

This file was deleted.

36 changes: 36 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,42 @@ const nextConfig = {
port: '',
pathname: '/**',
},
{
protocol: 'https',
hostname: 'raw.githubusercontent.com', // TODO: this one can be dangerous
port: '',
pathname: '/lifinance/types/main/src/assets/**',
},
{
protocol: 'https',
hostname: 'assets.coingecko.com',
port: '',
pathname: '/**',
},
{
protocol: 'https',
hostname: 's2.coinmarketcap.com',
port: '',
pathname: '/**',
},
{
protocol: 'https',
hostname: 'static.debank.com',
port: '',
pathname: '/**',
},
{
protocol: 'https',
hostname: 'cdn.sei.io',
port: '',
pathname: '/**',
},
{
protocol: 'https',
hostname: '*.etherscan.io',
port: '',
pathname: '/token/images/**',
},
],
},
async redirects() {
Expand Down
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
"i18next-resources-to-backend": "^1.2.1",
"next": "^14.2.12",
"next-i18n-router": "^5.5.1",
"next-sitemap": "^4.2.3",
"next-themes": "^0.3.0",
"react": "^18.3.1",
"react-cookie": "^7.2.0",
Expand Down Expand Up @@ -88,7 +87,6 @@
"dev:staging": "dotenv -e .env.staging next dev",
"dev:production": "dotenv -e .env.production next dev",
"build": "next build",
"postbuild": "next-sitemap",
"start": "next start",
"lint": "next lint",
"lint_es": "eslint . --ext .ts,.tsx,.js,.jsx",
Expand Down
69 changes: 28 additions & 41 deletions src/app/[lng]/scan/[[...segments]]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,36 @@
'use client';
import { LiFiExplorer } from '@lifi/explorer';
import type { PaletteMode } from '@mui/material';
import { alpha, Box, useTheme } from '@mui/material';
import { useMemo } from 'react';
import { ClientOnly } from 'src/components/ClientOnly';
import { fallbackLng } from 'src/i18n';
import { JUMPER_SCAN_PATH } from '@/const/urls';
import ScanPage from '@/app/ui/scan/ScanPage';
import type { Metadata } from 'next';

export async function generateMetadata({
params: { segments },
}: {
params: {
segments: string[];
};
}): Promise<Metadata> {
const slugToTitle: { [key: string]: string } = {
tx: 'Transaction',
block: 'Block',
wallet: 'wallet',
};

const [slug, address] = segments;

return {
title: `Jumper Scan | ${slugToTitle[slug]} ${address}`,
description:
'Jumper Scan is a blockchain explorer that allows you to search and explore transactions, blocks, and wallets on multiple blockchains.',
alternates: {
canonical: `${process.env.NEXT_PUBLIC_SITE_URL}/scan/${segments.join('/')}`,
},
};
}

export default function Page({
params: { lng },
}: {
children: React.ReactNode;
params: { lng: string };
}) {
const theme = useTheme();

const explorerConfig = useMemo(
() => ({
appearance: 'light' as PaletteMode, //theme.palette.mode, // This controls light and dark mode
integrator: process.env.NEXT_PUBLIC_WIDGET_INTEGRATOR, // TODO: change as needed
base: `${lng !== fallbackLng ? `${lng}` : ''}${JUMPER_SCAN_PATH}`, // Important for the routing and having everything served under /scan. Do not remove!
theme: {
// These colors and values correspond to the figma design
shape: { borderRadiusSecondary: 900, borderRadius: 12 },
palette: {
background: {
default: alpha(theme.palette.white.main, 0.8),
paper: alpha(theme.palette.white.main, 0.8),
},
},
},
}),
[lng, theme.palette.mode, theme.palette.white.main],
);

return (
<ClientOnly>
<Box
sx={{
p: 4,
paddingBottom: 8,
}}
>
<LiFiExplorer config={explorerConfig} />
</Box>
</ClientOnly>
);
return <ScanPage lng={lng} />;
}
7 changes: 1 addition & 6 deletions src/app/[lng]/scan/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
import { ThemeProviderV2 } from '@/providers/ThemeProviderV2';
import { ThemeProvider as NextThemeProvider } from 'next-themes';
import { cookies } from 'next/headers';
import React from 'react';
import { Layout } from 'src/Layout';

export default async function PartnerThemeLayout({
export default async function RootLayout({
children,
params: { partnerTheme },
}: {
children: React.ReactNode;
params: { partnerTheme: string };
}) {
const cookiesHandler = cookies();

return (
<NextThemeProvider
themes={['light']}
Expand Down
130 changes: 130 additions & 0 deletions src/app/bridge/[segments]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import BridgePage from '@/app/ui/bridge/BridgePage';
import { getChainsQuery } from '@/hooks/useChains';
import { getTokensQuery } from '@/hooks/useTokens';
import { notFound } from 'next/navigation';
import {
getChainByName,
getTokenBySymbolOnSpecificChain,
} from '@/utils/tokenAndChain';
import type { Metadata } from 'next';
import { sliceStrToXChar } from '@/utils/splitStringToXChar';
import { siteName } from '@/app/lib/metadata';

function parseString(url: string): [string, string, string, string] {
// First, split the string into the source part and the destination part using 'to'
const [sourcePart, destinationPart] = url.split('-to-');

if (!sourcePart || !destinationPart) {
throw new Error(
'Invalid format. Expected format: sourceChain-sourceToken-to-destinationChain-destinationToken',
);
}

// Split the source part into chain and token
const sourceSplit = sourcePart.split('-');
const destinationSplit = destinationPart.split('-');

// Source Chain will always be the first element, and the rest is the token
const sourceChain = sourceSplit[0];
const sourceToken = sourceSplit.slice(1).join('-'); // Join the rest back in case of dashes in the token name

// Destination Chain will always be the first element of the destination part, and the rest is the token
const destinationChain = destinationSplit[0];
const destinationToken = destinationSplit.slice(1).join('-'); // Join the rest back for destination token

return [sourceChain, sourceToken, destinationChain, destinationToken];
}
export async function generateMetadata({
params,
}: {
params: { segments: string };
}): Promise<Metadata> {
const [sourceChain, sourceTokenName, destinationChain, destinationTokenName] =
parseString(params.segments);

const title = `Jumper | Best way to bridge from ${sourceTokenName} on ${sourceChain} to ${destinationTokenName} on ${destinationChain}`;

const openGraph: Metadata['openGraph'] = {
title: title,
description: `Jumper offers the best way to do cross-chain bridging of ${sourceTokenName} on ${sourceChain} to ${destinationTokenName} on ${destinationChain} with the fastest speeds, lowest costs, and most secure bridge and swap providers available.`,
siteName: siteName,
url: `${process.env.NEXT_PUBLIC_SITE_URL}/bridge/${params.segments}`,
/* images: [
{
url: `${article.url}${articleData.Image.data.attributes?.url}`,
width: 900,
height: 450,
alt: 'banner image',
},
],*/
type: 'article',
};

return {
title,
description: title,
twitter: openGraph,
openGraph,
};
}

export const revalidate = 86400;
export const dynamicParams = true; // or false, to 404 on unknown paths
export const dynamic = 'force-dynamic';

export async function generateStaticParams() {
return [];
}

export default async function Page({
params: { segments },
}: {
params: { segments: string };
}) {
try {
const [
sourceChainNameParam,
sourceTokenSymbolParam,
destinationChainNameParam,
destinationTokenSymbolParam,
] = parseString(decodeURIComponent(segments));

const { chains } = await getChainsQuery();
const { tokens } = await getTokensQuery();

const sourceChain = getChainByName(chains, sourceChainNameParam);
const sourceToken = getTokenBySymbolOnSpecificChain(
tokens,
sourceChain?.id ?? 0,
sourceTokenSymbolParam,
);
const destinationChain = getChainByName(chains, destinationChainNameParam);
const destinationToken = getTokenBySymbolOnSpecificChain(
tokens,
destinationChain?.id ?? 0,
destinationTokenSymbolParam,
);

if (
!sourceChain ||
!sourceToken ||
!destinationChain ||
!destinationToken
) {
return notFound();
}

return (
<BridgePage
sourceChain={sourceChain}
sourceToken={sourceToken}
destinationChain={destinationChain}
destinationToken={destinationToken}
chains={chains}
tokens={tokens}
/>
);
} catch (e) {
notFound();
}
}
94 changes: 94 additions & 0 deletions src/app/bridge/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React from 'react';
import { ThemeProviderV2 } from '@/providers/ThemeProviderV2';
import { Layout } from 'src/Layout';
import { ThemeProvider as NextThemeProvider } from 'next-themes';
import { defaultNS, fallbackLng, namespaces } from 'src/i18n';
import { fonts } from '@/fonts/fonts';
import Script from 'next/script';
import { PixelBg } from '@/components/illustrations/PixelBg';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v14-appRouter';
import { ReactQueryProvider } from '@/providers/ReactQueryProvider';
import { WalletProvider } from '@/providers/WalletProvider';
import TranslationsProvider from '@/providers/TranslationProvider';
import initTranslations from '@/app/i18n';

export default async function MainLayout({
children,
}: {
children: React.ReactNode;
params: { lng: string };
}) {
const { resources } = await initTranslations(fallbackLng, namespaces);

const defaultTheme = 'default';

// provider for the theme context, it is used to provide the theme to the whole app, must be into the layout.tsx or page.tsx.
return (
<html
lang={fallbackLng}
suppressHydrationWarning
className={fonts.map((f) => f.variable).join(' ')}
>
<head>
<link rel="icon" href="/favicon.ico" sizes="any" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<Script
async
src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS_TRACKING_ID}`}
/>
<Script id="google-analytics">
{`
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', '${process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS_TRACKING_ID}');
`}
</Script>
<Script id="addressable-tracker">
{`
!function(w, d){
w.__adrsbl = {
queue: [],
run: function(){
this.queue.push(arguments);
}
};
var s = d.createElement('script');
s.async = true;
s.src = 'https://tag.adrsbl.io/p.js?tid=${process.env.NEXT_PUBLIC_ADDRESSABLE_TID}';
var b = d.getElementsByTagName('script')[0];
b.parentNode.insertBefore(s, b);
}(window, document);
`}
</Script>
</head>

<body suppressHydrationWarning>
<AppRouterCacheProvider>
<ReactQueryProvider>
<WalletProvider>
<TranslationsProvider
namespaces={[defaultNS]}
locale={fallbackLng}
resources={resources}
>
<NextThemeProvider
themes={['dark', 'light']}
defaultTheme={defaultTheme}
enableSystem
enableColorScheme
>
<ThemeProviderV2 activeTheme={defaultTheme} themes={[]}>
<Layout>{children}</Layout>
</ThemeProviderV2>
</NextThemeProvider>
</TranslationsProvider>

<PixelBg />
</WalletProvider>
</ReactQueryProvider>
</AppRouterCacheProvider>
</body>
</html>
);
}
Loading

1 comment on commit bdde13d

@vercel
Copy link

@vercel vercel bot commented on bdde13d Oct 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.