Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 48 additions & 44 deletions app/account/[ownerEthAddr]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import ClientWrapper from '@/components/shared/ClientWrapper';
import { CopyableAddress } from '@/components/shared/CopyableValue';
import config from '@/config';
import { getPublicProfiles } from '@/lib/api/backend';
import { fetchCSPDetails, fetchErc20Balance, getLicenses } from '@/lib/api/blockchain';
import { fetchCSPDetails, fetchErc20Balance } from '@/lib/api/blockchain';
import { cachedGetLicenses } from '@/lib/api/cache';
import { cachedGetENSName, fBI, getShortAddress, isZeroAddress } from '@/lib/utils';
import * as types from '@/typedefs/blockchain';
import type { PublicProfileInfo } from '@/typedefs/general';
Expand All @@ -30,48 +31,48 @@ const getCachedNodeOperatorProfile = unstable_cache(
{ revalidate: 60 },
);

export async function generateMetadata({ params }) {
const { ownerEthAddr } = await params;
const errorMetadata = {
title: 'Error',
openGraph: {
title: 'Error',
},
};

if (!ownerEthAddr || !isAddress(ownerEthAddr) || isZeroAddress(ownerEthAddr)) {
return errorMetadata;
}

const canonical = `/account/${encodeURIComponent(ownerEthAddr)}`;
const errorMetadataWithCanonical = {
...errorMetadata,
alternates: {
canonical,
},
};

try {
const [ensName, publicProfile] = await Promise.all([
cachedGetENSName(ownerEthAddr),
getCachedNodeOperatorProfile(ownerEthAddr as types.EthAddress),
export async function generateMetadata({ params }) {
const { ownerEthAddr } = await params;
const errorMetadata = {
title: 'Error',
openGraph: {
title: 'Error',
},
};
if (!ownerEthAddr || !isAddress(ownerEthAddr) || isZeroAddress(ownerEthAddr)) {
return errorMetadata;
}
const canonical = `/account/${encodeURIComponent(ownerEthAddr)}`;
const errorMetadataWithCanonical = {
...errorMetadata,
alternates: {
canonical,
},
};
try {
const [ensName, publicProfile] = await Promise.all([
cachedGetENSName(ownerEthAddr),
getCachedNodeOperatorProfile(ownerEthAddr as types.EthAddress),
]);

const primaryName = publicProfile?.name || ensName || getShortAddress(ownerEthAddr, 4, true);

return {
title: `Node Operator • ${primaryName}`,
openGraph: {
title: `Node Operator • ${primaryName}`,
},
alternates: {
canonical,
},
};
} catch (error) {
return errorMetadataWithCanonical;
}
}
return {
title: `Node Operator • ${primaryName}`,
openGraph: {
title: `Node Operator • ${primaryName}`,
},
alternates: {
canonical,
},
};
} catch (error) {
return errorMetadataWithCanonical;
}
}

export default async function NodeOperatorPage({ params }) {
const { ownerEthAddr } = await params;
Expand All @@ -81,15 +82,15 @@ export default async function NodeOperatorPage({ params }) {
return <NotFound />;
}

let licenses: types.LicenseInfo[],
let licenses: types.CachedLicense[],
ensName: string | undefined,
r1Balance: bigint,
publicProfileInfo: PublicProfileInfo | undefined,
cspDetails: types.CSP | undefined;

try {
[licenses, ensName, r1Balance, publicProfileInfo, cspDetails] = await Promise.all([
getLicenses(ownerEthAddr),
cachedGetLicenses(ownerEthAddr),
cachedGetENSName(ownerEthAddr),
fetchErc20Balance(ownerEthAddr, config.r1ContractAddress),
getCachedNodeOperatorProfile(ownerEthAddr as types.EthAddress),
Expand Down Expand Up @@ -133,7 +134,7 @@ export default async function NodeOperatorPage({ params }) {
value={
<div className="text-primary">
{fBI(
licenses.reduce((acc, license) => acc + license.totalClaimedAmount, 0n),
licenses.reduce((acc, license) => acc + BigInt(license.totalClaimedAmount), 0n),
18,
)}
</div>
Expand All @@ -148,9 +149,12 @@ export default async function NodeOperatorPage({ params }) {
value={
<div className="w-full min-w-52 xs:min-w-56 md:min-w-60">
<UsageStats
totalClaimedAmount={licenses.reduce((acc, license) => acc + license.totalClaimedAmount, 0n)}
totalClaimedAmount={licenses.reduce(
(acc, license) => acc + BigInt(license.totalClaimedAmount),
0n,
)}
totalAssignedAmount={licenses.reduce(
(acc, license) => acc + license.totalAssignedAmount,
(acc, license) => acc + BigInt(license.totalAssignedAmount),
0n,
)}
/>
Expand Down
12 changes: 6 additions & 6 deletions app/cloud-service-providers/loading.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { PAGE_SIZE } from '@/config';
import { Skeleton } from '@heroui/skeleton';

export default function Loading() {
Expand All @@ -8,12 +9,11 @@ export default function Loading() {
<div className="col w-full gap-2">
<Skeleton className="only-lg min-h-[56px] w-full rounded-xl" />

<Skeleton className="min-h-[68px] w-full rounded-2xl lg:min-h-[60px]" />
<Skeleton className="min-h-[68px] w-full rounded-2xl lg:min-h-[60px]" />
<Skeleton className="min-h-[68px] w-full rounded-2xl lg:min-h-[60px]" />
<Skeleton className="min-h-[68px] w-full rounded-2xl lg:min-h-[60px]" />
<Skeleton className="min-h-[68px] w-full rounded-2xl lg:min-h-[60px]" />
<Skeleton className="min-h-[68px] w-full rounded-2xl lg:min-h-[60px]" />
{Array(PAGE_SIZE)
.fill(null)
.map((_, index) => (
<Skeleton key={index} className="min-h-[68px] w-full rounded-2xl lg:min-h-[60px]" />
))}
</div>
</div>
);
Expand Down
34 changes: 16 additions & 18 deletions app/cloud-service-providers/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,22 @@ import CSPsList from '../server-components/CPSs/CSPsList';
import { BorderedCard } from '../server-components/shared/cards/BorderedCard';
import { CardHorizontal } from '../server-components/shared/cards/CardHorizontal';

export async function generateMetadata({ searchParams }: { searchParams?: Promise<{ page?: string }> }) {
const resolvedSearchParams = await searchParams;
const pageParam = Number.parseInt(resolvedSearchParams?.page ?? '', 10);
const canonical =
Number.isFinite(pageParam) && pageParam > 1
? `/cloud-service-providers?page=${pageParam}`
: '/cloud-service-providers';

return {
title: 'Cloud Service Providers',
openGraph: {
title: 'Cloud Service Providers',
},
alternates: {
canonical,
},
};
}
export async function generateMetadata({ searchParams }: { searchParams?: Promise<{ page?: string }> }) {
const resolvedSearchParams = await searchParams;
const pageParam = Number.parseInt(resolvedSearchParams?.page ?? '', 10);
const canonical =
Number.isFinite(pageParam) && pageParam > 1 ? `/cloud-service-providers?page=${pageParam}` : '/cloud-service-providers';

return {
title: 'Cloud Service Providers',
openGraph: {
title: 'Cloud Service Providers',
},
alternates: {
canonical,
},
};
}

export default async function CSPsPage(props: {
searchParams?: Promise<{
Expand Down
10 changes: 6 additions & 4 deletions app/licenses/loading.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { PAGE_SIZE } from '@/config';
import { Skeleton } from '@heroui/skeleton';

export default function Loading() {
Expand All @@ -8,10 +9,11 @@ export default function Loading() {
<div className="col w-full gap-2">
<Skeleton className="only-lg min-h-[56px] w-full rounded-2xl" />

<Skeleton className="min-h-[92px] w-full rounded-2xl" />
<Skeleton className="min-h-[92px] w-full rounded-2xl" />
<Skeleton className="min-h-[92px] w-full rounded-2xl" />
<Skeleton className="min-h-[92px] w-full rounded-2xl" />
{Array(PAGE_SIZE)
.fill(null)
.map((_, index) => (
<Skeleton key={index} className="min-h-[92px] w-full rounded-2xl" />
))}
</div>
</div>
);
Expand Down
47 changes: 27 additions & 20 deletions app/licenses/page.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
import ErrorComponent from '@/app/server-components/shared/ErrorComponent';
import { getLicensesTotalSupply } from '@/lib/api/blockchain';
import { LicenseItem } from '@/typedefs/general';
import { unstable_cache } from 'next/cache';
import List from '../server-components/Licenses/List';
import { BorderedCard } from '../server-components/shared/cards/BorderedCard';
import { CardHorizontal } from '../server-components/shared/cards/CardHorizontal';

export async function generateMetadata({ searchParams }: { searchParams?: Promise<{ page?: string }> }) {
const resolvedSearchParams = await searchParams;
const pageParam = Number.parseInt(resolvedSearchParams?.page ?? '', 10);
const canonical = Number.isFinite(pageParam) && pageParam > 1 ? `/licenses?page=${pageParam}` : '/licenses';

return {
title: 'Licenses',
openGraph: {
title: 'Licenses',
},
alternates: {
canonical,
},
};
}
export async function generateMetadata({ searchParams }: { searchParams?: Promise<{ page?: string }> }) {
const resolvedSearchParams = await searchParams;
const pageParam = Number.parseInt(resolvedSearchParams?.page ?? '', 10);
const canonical = Number.isFinite(pageParam) && pageParam > 1 ? `/licenses?page=${pageParam}` : '/licenses';

return {
title: 'Licenses',
openGraph: {
title: 'Licenses',
},
alternates: {
canonical,
},
};
}

const getCachedSupply = unstable_cache(getLicensesTotalSupply, ['licenses-total-supply'], { revalidate: 300 });

export default async function LicensesPage(props: {
searchParams?: Promise<{
Expand All @@ -29,11 +32,15 @@ export default async function LicensesPage(props: {
const searchParams = await props.searchParams;
const currentPage = Number(searchParams?.page) || 1;

let ndTotalSupply: bigint, mndTotalSupply: bigint;
let ndTotalSupply: number, mndTotalSupply: number;
let licenses: LicenseItem[];

try {
({ ndTotalSupply, mndTotalSupply } = await getLicensesTotalSupply());
const { ndTotalSupply: ndTotalSupplyStr, mndTotalSupply: mndTotalSupplyStr } = await getCachedSupply();

ndTotalSupply = Number(ndTotalSupplyStr);
mndTotalSupply = Number(mndTotalSupplyStr);

licenses = [
...Array.from({ length: Number(mndTotalSupply) }, (_, i) => ({
licenseId: i + 1,
Expand All @@ -59,12 +66,12 @@ export default async function LicensesPage(props: {
<div className="flexible-row">
<CardHorizontal
label="Total"
value={Number(ndTotalSupply + mndTotalSupply)}
value={ndTotalSupply + mndTotalSupply}
isFlexible
widthClasses="min-w-[192px]"
/>
<CardHorizontal label="ND" value={Number(ndTotalSupply)} isFlexible widthClasses="min-w-[192px]" />
<CardHorizontal label="MND" value={Number(mndTotalSupply)} isFlexible widthClasses="min-w-[192px]" />
<CardHorizontal label="ND" value={ndTotalSupply} isFlexible widthClasses="min-w-[192px]" />
<CardHorizontal label="MND" value={mndTotalSupply} isFlexible widthClasses="min-w-[192px]" />
</div>
</BorderedCard>
</div>
Expand Down
12 changes: 6 additions & 6 deletions app/loading.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { PAGE_SIZE } from '@/config';
import { Skeleton } from '@heroui/skeleton';

export default function Loading() {
Expand All @@ -8,12 +9,11 @@ export default function Loading() {
<div className="col w-full gap-2">
<Skeleton className="only-lg min-h-[56px] w-full rounded-xl" />

<Skeleton className="min-h-[84px] w-full rounded-2xl" />
<Skeleton className="min-h-[84px] w-full rounded-2xl" />
<Skeleton className="min-h-[84px] w-full rounded-2xl" />
<Skeleton className="min-h-[84px] w-full rounded-2xl" />
<Skeleton className="min-h-[84px] w-full rounded-2xl" />
<Skeleton className="min-h-[84px] w-full rounded-2xl" />
{Array(PAGE_SIZE)
.fill(null)
.map((_, index) => (
<Skeleton key={index} className="min-h-[84px] w-full rounded-2xl" />
))}
</div>
</div>
);
Expand Down
12 changes: 6 additions & 6 deletions app/node-operators/loading.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { PAGE_SIZE } from '@/config';
import { Skeleton } from '@heroui/skeleton';

export default function Loading() {
Expand All @@ -8,12 +9,11 @@ export default function Loading() {
<div className="col w-full gap-2">
<Skeleton className="only-lg min-h-[56px] w-full rounded-xl" />

<Skeleton className="min-h-[68px] w-full rounded-2xl lg:min-h-[60px]" />
<Skeleton className="min-h-[68px] w-full rounded-2xl lg:min-h-[60px]" />
<Skeleton className="min-h-[68px] w-full rounded-2xl lg:min-h-[60px]" />
<Skeleton className="min-h-[68px] w-full rounded-2xl lg:min-h-[60px]" />
<Skeleton className="min-h-[68px] w-full rounded-2xl lg:min-h-[60px]" />
<Skeleton className="min-h-[68px] w-full rounded-2xl lg:min-h-[60px]" />
{Array(PAGE_SIZE)
.fill(null)
.map((_, index) => (
<Skeleton key={index} className="min-h-[68px] w-full rounded-2xl lg:min-h-[60px]" />
))}
</div>
</div>
);
Expand Down
31 changes: 15 additions & 16 deletions app/node-operators/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,21 @@ import List from '../server-components/NodeOperators/List';
import { BorderedCard } from '../server-components/shared/cards/BorderedCard';
import { CardHorizontal } from '../server-components/shared/cards/CardHorizontal';

export async function generateMetadata({ searchParams }: { searchParams?: Promise<{ page?: string }> }) {
const resolvedSearchParams = await searchParams;
const pageParam = Number.parseInt(resolvedSearchParams?.page ?? '', 10);
const canonical =
Number.isFinite(pageParam) && pageParam > 1 ? `/node-operators?page=${pageParam}` : '/node-operators';

return {
title: 'Node Operators',
openGraph: {
title: 'Node Operators',
},
alternates: {
canonical,
},
};
}
export async function generateMetadata({ searchParams }: { searchParams?: Promise<{ page?: string }> }) {
const resolvedSearchParams = await searchParams;
const pageParam = Number.parseInt(resolvedSearchParams?.page ?? '', 10);
const canonical = Number.isFinite(pageParam) && pageParam > 1 ? `/node-operators?page=${pageParam}` : '/node-operators';

return {
title: 'Node Operators',
openGraph: {
title: 'Node Operators',
},
alternates: {
canonical,
},
};
}

const fetchLicenseHolders = async (environment: 'mainnet' | 'testnet' | 'devnet') => {
const url = await getSSURL(`license-holders?env=${environment}`);
Expand Down
Loading