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
4 changes: 2 additions & 2 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const viewport: Viewport = {
export async function generateMetadata(): Promise<Metadata> {
return buildMetadata(
'Ratio1 Explorer',
'Experience the power of Ratio1 AI OS, built on Ratio1 Protocol and powered by blockchain, democratizing AI to empower limitless innovation.',
'Explore the Ratio1 network with Ratio1 Explorer - a real-time explorer providing transparent insights, analytics, and live network metrics.',
config.publicUrl,
);
}
Expand All @@ -45,7 +45,7 @@ export default async function RootLayout({
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta
name="description"
content="Experience the power of Ratio1 AI OS, built on Ratio1 Protocol and powered by blockchain, democratizing AI to empower limitless innovation."
content="Explore the Ratio1 network with Ratio1 Explorer - a real-time explorer providing transparent insights, analytics, and live network metrics."
/>
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
Expand Down
18 changes: 9 additions & 9 deletions app/manifest.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { MetadataRoute } from 'next';

export default async function manifest(): Promise<MetadataRoute.Manifest> {
return {
name: 'Ratio1 Explorer',
short_name: 'Ratio1 Explorer',
description:
'Experience the power of Ratio1 AI OS, built on Ratio1 Protocol and powered by blockchain, democratizing AI to empower limitless innovation.',
icons: [
{ src: '/android-chrome-192x192.png', sizes: '192x192', type: 'image/png' },
{ src: '/android-chrome-512x512.png', sizes: '512x512', type: 'image/png' },
],
return {
name: 'Ratio1 Explorer',
short_name: 'Ratio1 Explorer',
description:
'Explore the Ratio1 network with Ratio1 Explorer - a real-time explorer providing transparent insights, analytics, and live network metrics.',
icons: [
{ src: '/android-chrome-192x192.png', sizes: '192x192', type: 'image/png' },
{ src: '/android-chrome-512x512.png', sizes: '512x512', type: 'image/png' },
],
start_url: '/',
theme_color: '#1b47f7',
background_color: '#1b47f7',
Expand Down
315 changes: 155 additions & 160 deletions app/server-components/main-cards/LicenseCard.tsx
Original file line number Diff line number Diff line change
@@ -1,160 +1,155 @@
import LicenseRewardsPoA from '@/app/server-components/Licenses/LicenseRewardsPoA';
import { BorderedCard } from '@/app/server-components/shared/cards/BorderedCard';
import { CardHorizontal } from '@/app/server-components/shared/cards/CardHorizontal';
import ClientWrapper from '@/components/shared/ClientWrapper';
import { CopyableAddress } from '@/components/shared/CopyableValue';
import config from '@/config';
import { routePath } from '@/lib/routes';
import { fBI } from '@/lib/utils';
import * as types from '@/typedefs/blockchain';
import { Skeleton } from '@heroui/skeleton';
import clsx from 'clsx';
import Link from 'next/link';
import { Suspense } from 'react';
import { formatUnits } from 'viem';
import PoA from '../Licenses/PoA';
import TreasuryWallets from '../Licenses/TreasuryWallets';
import { CardTitle } from '../shared/CardTitle';
import { LargeTag } from '../shared/LargeTag';
import UsageStats from '../shared/Licenses/UsageStats';

interface Props {
license: types.License;
licenseType: 'ND' | 'MND' | 'GND';
licenseId: string;
owner: types.EthAddress;
getNodeAvailability: () => Promise<(types.OraclesAvailabilityResult & types.OraclesDefaultResult) | undefined>;
hasLink?: boolean; // If it has a link to it, it means it's not the main card (displayed on top of the page)
}

export default async function LicenseCard({ license, licenseType, licenseId, owner, getNodeAvailability, hasLink }: Props) {
const environment = config.environment;
const awbBalance = license.awbBalance;

const getTitle = () => <CardTitle hasLink={hasLink}>License #{licenseId}</CardTitle>;

return (
<BorderedCard>
<div className="row gap-3">
{!hasLink ? (
getTitle()
) : (
<Link href={`${routePath.license}/${licenseType}/${licenseId}`} className="hover:text-primary">
{getTitle()}
</Link>
)}

{license.isBanned && <LargeTag variant="banned">Banned</LargeTag>}
</div>

<div className="flexible-row">
{!!licenseType && (
<CardHorizontal
label="Type"
value={
<div
className={clsx({
'text-primary': licenseType === 'ND',
'text-purple-600': licenseType === 'MND',
'text-orange-600': licenseType === 'GND',
})}
>
{licenseType}
</div>
}
isSmall
isFlexible
/>
)}

{!!owner && (
<CardHorizontal
label="Owner"
value={
<ClientWrapper>
<CopyableAddress value={owner} size={4} isLarge link={`${routePath.account}/${owner}`} />
</ClientWrapper>
}
isSmall
isFlexible
/>
)}

{!!license.assignTimestamp && (
<CardHorizontal
label="Assign timestamp"
value={new Date(Number(license.assignTimestamp) * 1000).toLocaleString()}
isSmaller
isFlexible
widthClasses="min-w-[310px] md:min-w-[420px]"
/>
)}

{!!license.lastClaimEpoch && (
<CardHorizontal
label="Last claim epoch"
value={license.lastClaimEpoch.toString()}
isSmall
isFlexible
widthClasses="min-w-[274px]"
/>
)}

<CardHorizontal
label="Usage"
value={
<div className="w-full min-w-52 xs:min-w-56 md:min-w-60">
<UsageStats
totalClaimedAmount={license.totalClaimedAmount}
totalAssignedAmount={license.totalAssignedAmount}
awbBalance={license.awbBalance}
/>
</div>
}
isSmall
isFlexible
/>

<PoA totalAssignedAmount={license.totalAssignedAmount} totalClaimedAmount={license.totalClaimedAmount} />

{licenseType !== 'ND' && (
<CardHorizontal
label="Adoption Withheld Buffer"
value={<div className="text-orange-500">{fBI(awbBalance, 18)} $R1</div>}
isSmall
isFlexible
widthClasses="min-w-[360px]"
/>
)}

<Suspense fallback={<Skeleton className="min-h-[76px] w-full rounded-xl md:max-w-[258px]" />}>
<LicenseRewardsPoA
license={license}
licenseType={licenseType as 'ND' | 'MND' | 'GND'}
licenseId={licenseId}
getNodeAvailability={getNodeAvailability}
/>
</Suspense>

{licenseType === 'ND' && (
<CardHorizontal
label="Rewards (PoAI)"
value={
<div className="text-primary">
{license.r1PoaiRewards === undefined
? '...'
: parseFloat(
Number(formatUnits(license.r1PoaiRewards ?? 0n, 18)).toFixed(2),
).toLocaleString()}
{!!license.r1PoaiRewards ? ' $R1' : ''}
</div>
}
isSmall
/>
)}
</div>

{environment === 'mainnet' && licenseId === '1' && licenseType === 'GND' && <TreasuryWallets license={license} />}
</BorderedCard>
);
}
import LicenseRewardsPoA from '@/app/server-components/Licenses/LicenseRewardsPoA';
import { BorderedCard } from '@/app/server-components/shared/cards/BorderedCard';
import { CardHorizontal } from '@/app/server-components/shared/cards/CardHorizontal';
import ClientWrapper from '@/components/shared/ClientWrapper';
import { CopyableAddress } from '@/components/shared/CopyableValue';
import { routePath } from '@/lib/routes';
import { fBI } from '@/lib/utils';
import * as types from '@/typedefs/blockchain';
import { Skeleton } from '@heroui/skeleton';
import clsx from 'clsx';
import Link from 'next/link';
import { Suspense } from 'react';
import { formatUnits } from 'viem';
import PoA from '../Licenses/PoA';
import { CardTitle } from '../shared/CardTitle';
import { LargeTag } from '../shared/LargeTag';
import UsageStats from '../shared/Licenses/UsageStats';

interface Props {
license: types.License;
licenseType: 'ND' | 'MND' | 'GND';
licenseId: string;
owner: types.EthAddress;
getNodeAvailability: () => Promise<(types.OraclesAvailabilityResult & types.OraclesDefaultResult) | undefined>;
hasLink?: boolean; // If it has a link to it, it means it's not the main card (displayed on top of the page)
}

export default async function LicenseCard({ license, licenseType, licenseId, owner, getNodeAvailability, hasLink }: Props) {
const awbBalance = license.awbBalance;

const getTitle = () => <CardTitle hasLink={hasLink}>License #{licenseId}</CardTitle>;

return (
<BorderedCard>
<div className="row gap-3">
{!hasLink ? (
getTitle()
) : (
<Link href={`${routePath.license}/${licenseType}/${licenseId}`} className="hover:text-primary">
{getTitle()}
</Link>
)}

{license.isBanned && <LargeTag variant="banned">Banned</LargeTag>}
</div>

<div className="flexible-row">
{!!licenseType && (
<CardHorizontal
label="Type"
value={
<div
className={clsx({
'text-primary': licenseType === 'ND',
'text-purple-600': licenseType === 'MND',
'text-orange-600': licenseType === 'GND',
})}
>
{licenseType}
</div>
}
isSmall
isFlexible
/>
)}

{!!owner && (
<CardHorizontal
label="Owner"
value={
<ClientWrapper>
<CopyableAddress value={owner} size={4} isLarge link={`${routePath.account}/${owner}`} />
</ClientWrapper>
}
isSmall
isFlexible
/>
)}

{!!license.assignTimestamp && (
<CardHorizontal
label="Assign timestamp"
value={new Date(Number(license.assignTimestamp) * 1000).toLocaleString()}
isSmaller
isFlexible
widthClasses="min-w-[310px] md:min-w-[420px]"
/>
)}

{!!license.lastClaimEpoch && (
<CardHorizontal
label="Last claim epoch"
value={license.lastClaimEpoch.toString()}
isSmall
isFlexible
widthClasses="min-w-[274px]"
/>
)}

<CardHorizontal
label="Usage"
value={
<div className="w-full min-w-52 xs:min-w-56 md:min-w-60">
<UsageStats
totalClaimedAmount={license.totalClaimedAmount}
totalAssignedAmount={license.totalAssignedAmount}
awbBalance={license.awbBalance}
/>
</div>
}
isSmall
isFlexible
/>

<PoA totalAssignedAmount={license.totalAssignedAmount} totalClaimedAmount={license.totalClaimedAmount} />

{licenseType !== 'ND' && (
<CardHorizontal
label="Adoption Withheld Buffer"
value={<div className="text-orange-500">{fBI(awbBalance, 18)} $R1</div>}
isSmall
isFlexible
widthClasses="min-w-[360px]"
/>
)}

<Suspense fallback={<Skeleton className="min-h-[76px] w-full rounded-xl md:max-w-[258px]" />}>
<LicenseRewardsPoA
license={license}
licenseType={licenseType as 'ND' | 'MND' | 'GND'}
licenseId={licenseId}
getNodeAvailability={getNodeAvailability}
/>
</Suspense>

{licenseType === 'ND' && (
<CardHorizontal
label="Rewards (PoAI)"
value={
<div className="text-primary">
{license.r1PoaiRewards === undefined
? '...'
: parseFloat(
Number(formatUnits(license.r1PoaiRewards ?? 0n, 18)).toFixed(2),
).toLocaleString()}
{!!license.r1PoaiRewards ? ' $R1' : ''}
</div>
}
isSmall
/>
)}
</div>
</BorderedCard>
);
}
Loading