diff --git a/.eslintrc.json b/.eslintrc.json index 9c4c2b06..01ddf359 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,5 +1,11 @@ { "extends": ["next/core-web-vitals", "@solana/eslint-config-solana"], + "rules": { + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-duplicate-enum-values" : "off", + "simple-import-sort/imports": "off" + }, "plugins": ["testing-library"], "overrides": [ // Only uses Testing Library lint rules in test files diff --git a/README.md b/README.md index c089060c..5d04da62 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- Solana + Eclipse

# Solana Explorer diff --git a/amplify.yml b/amplify.yml new file mode 100644 index 00000000..c688b56d --- /dev/null +++ b/amplify.yml @@ -0,0 +1,23 @@ + +version: 1 +frontend: + phases: + preBuild: + commands: + - npm i -g pnpm + - corepack enable + - pnpm install --frozen-lockfile + build: + commands: + - pnpm run build + postBuild: + commands: + - pwd + - ls -al + env: + variables: + node-linker: hoisted + artifacts: + baseDirectory: .next + files: + - '**/*' \ No newline at end of file diff --git a/app/address/[address]/anchor-account/page.tsx b/app/address/[address]/anchor-account/page.tsx index 64521e32..866de03a 100644 --- a/app/address/[address]/anchor-account/page.tsx +++ b/app/address/[address]/anchor-account/page.tsx @@ -11,8 +11,8 @@ type Props = Readonly<{ export async function generateMetadata(props: AddressPageMetadataProps): Promise { return { - description: `Contents of the Anchor Account at address ${props.params.address} on Solana`, - title: `Anchor Account Data | ${await getReadableTitleFromAddress(props)} | Solana`, + description: `Contents of the Anchor Account at address ${props.params.address} on Eclipse`, + title: `Anchor Account Data | ${await getReadableTitleFromAddress(props)} | Eclipse`, }; } diff --git a/app/address/[address]/anchor-program/page.tsx b/app/address/[address]/anchor-program/page.tsx index 986b5520..105f8178 100644 --- a/app/address/[address]/anchor-program/page.tsx +++ b/app/address/[address]/anchor-program/page.tsx @@ -12,8 +12,8 @@ type Props = Readonly<{ export async function generateMetadata(props: AddressPageMetadataProps): Promise { return { - description: `The Interface Definition Language (IDL) file for the Anchor program at address ${props.params.address} on Solana`, - title: `Anchor Program IDL | ${await getReadableTitleFromAddress(props)} | Solana`, + description: `The Interface Definition Language (IDL) file for the Anchor program at address ${props.params.address} on Eclipse`, + title: `Anchor Program IDL | ${await getReadableTitleFromAddress(props)} | Eclipse`, }; } diff --git a/app/address/[address]/attributes/page.tsx b/app/address/[address]/attributes/page.tsx index bec5eab9..46b69c5f 100644 --- a/app/address/[address]/attributes/page.tsx +++ b/app/address/[address]/attributes/page.tsx @@ -11,8 +11,8 @@ type Props = Readonly<{ export async function generateMetadata(props: AddressPageMetadataProps): Promise { return { - description: `Attributes of the Metaplex NFT with address ${props.params.address} on Solana`, - title: `Metaplex NFT Attributes | ${await getReadableTitleFromAddress(props)} | Solana`, + description: `Attributes of the Metaplex NFT with address ${props.params.address} on Eclipse`, + title: `Metaplex NFT Attributes | ${await getReadableTitleFromAddress(props)} | Eclipse`, }; } diff --git a/app/address/[address]/blockhashes/page.tsx b/app/address/[address]/blockhashes/page.tsx index 343df8c4..f1246e29 100644 --- a/app/address/[address]/blockhashes/page.tsx +++ b/app/address/[address]/blockhashes/page.tsx @@ -7,8 +7,8 @@ type Props = Readonly<{ }>; export const metadata = { - description: `Recent blockhashes on Solana`, - title: `Recent Blockhashes | Solana`, + description: `Recent blockhashes on Eclipse`, + title: `Recent Blockhashes | Eclipse`, }; export default function RecentBlockhashesPage(props: Props) { diff --git a/app/address/[address]/concurrent-merkle-tree/page.tsx b/app/address/[address]/concurrent-merkle-tree/page.tsx index 63ed4aaf..14f15a85 100644 --- a/app/address/[address]/concurrent-merkle-tree/page.tsx +++ b/app/address/[address]/concurrent-merkle-tree/page.tsx @@ -11,8 +11,8 @@ type Props = Readonly<{ export async function generateMetadata(props: AddressPageMetadataProps): Promise { return { - description: `Contents of the SPL Concurrent Merkle Tree at address ${props.params.address} on Solana`, - title: `Concurrent Merkle Tree | ${await getReadableTitleFromAddress(props)} | Solana`, + description: `Contents of the SPL Concurrent Merkle Tree at address ${props.params.address} on Eclipse`, + title: `Concurrent Merkle Tree | ${await getReadableTitleFromAddress(props)} | Eclipse`, }; } diff --git a/app/address/[address]/domains/page.tsx b/app/address/[address]/domains/page.tsx index 23a112dd..7c64c4ca 100644 --- a/app/address/[address]/domains/page.tsx +++ b/app/address/[address]/domains/page.tsx @@ -10,8 +10,8 @@ type Props = Readonly<{ export async function generateMetadata(props: AddressPageMetadataProps): Promise { return { - description: `Domain names owned by the address ${props.params.address} on Solana`, - title: `Domains | ${await getReadableTitleFromAddress(props)} | Solana`, + description: `Domain names owned by the address ${props.params.address} on Eclipse`, + title: `Domains | ${await getReadableTitleFromAddress(props)} | Eclipse`, }; } diff --git a/app/address/[address]/entries/page.tsx b/app/address/[address]/entries/page.tsx index 64613940..7ee77663 100644 --- a/app/address/[address]/entries/page.tsx +++ b/app/address/[address]/entries/page.tsx @@ -11,8 +11,8 @@ type Props = Readonly<{ export async function generateMetadata(props: AddressPageMetadataProps): Promise { return { - description: `Entries of the address lookup table at ${props.params.address} on Solana`, - title: `Address Lookup Table Entries | ${await getReadableTitleFromAddress(props)} | Solana`, + description: `Entries of the address lookup table at ${props.params.address} on Eclipse`, + title: `Address Lookup Table Entries | ${await getReadableTitleFromAddress(props)} | Eclipse`, }; } diff --git a/app/address/[address]/instructions/page.tsx b/app/address/[address]/instructions/page.tsx index 65d4aae1..62e99446 100644 --- a/app/address/[address]/instructions/page.tsx +++ b/app/address/[address]/instructions/page.tsx @@ -10,8 +10,8 @@ type Props = Readonly<{ export async function generateMetadata(props: AddressPageMetadataProps): Promise { return { - description: `A list of transactions that include an instruction involving the token with address ${props.params.address} on Solana`, - title: `Token Instructions | ${await getReadableTitleFromAddress(props)} | Solana`, + description: `A list of transactions that include an instruction involving the token with address ${props.params.address} on Eclipse`, + title: `Token Instructions | ${await getReadableTitleFromAddress(props)} | Eclipse`, }; } diff --git a/app/address/[address]/layout.tsx b/app/address/[address]/layout.tsx index a7cf6627..31c3320b 100644 --- a/app/address/[address]/layout.tsx +++ b/app/address/[address]/layout.tsx @@ -19,6 +19,7 @@ import { VoteAccountSection } from '@components/account/VoteAccountSection'; import { ErrorCard } from '@components/common/ErrorCard'; import { Identicon } from '@components/common/Identicon'; import { LoadingCard } from '@components/common/LoadingCard'; +import { Asset, ASSET_PROGRAM_ID, ExtensionType, getExtension, getInternalAssetAccountDataSerializer } from '@nifty-oss/asset'; import { Account, AccountsProvider, @@ -41,15 +42,19 @@ import { useClusterPath } from '@utils/url'; import { MetadataPointer, TokenMetadata } from '@validators/accounts/token-extension'; import Link from 'next/link'; import { redirect, useSelectedLayoutSegment } from 'next/navigation'; -import React, { PropsWithChildren, Suspense } from 'react'; +import React, { PropsWithChildren, Suspense, useMemo } from 'react'; import { ErrorBoundary } from 'react-error-boundary'; import { create } from 'superstruct'; import useSWRImmutable from 'swr/immutable'; import { Address } from 'web3js-experimental'; - +import { NiftyAssetAccountCard } from '@/app/components/account/nifty-asset/AssetAccountCard'; +import { NiftyAssetAccountHeader } from '@/app/components/account/nifty-asset/AssetAccountHeader'; +import { isNiftyAssetAccount } from '@/app/components/account/nifty-asset/types'; import { CompressedNftAccountHeader, CompressedNftCard } from '@/app/components/account/CompressedNftCard'; -import { useCompressedNft } from '@/app/providers/compressed-nft'; +import { useCompressedNft, useMetadataJsonLink } from '@/app/providers/compressed-nft'; import { FullTokenInfo, getFullTokenInfo } from '@/app/utils/token-info'; +import { MintAccountInfo } from '@/app/validators/accounts/token'; +import { BareFetcher } from 'swr'; const IDENTICON_WIDTH = 64; @@ -200,7 +205,7 @@ function AddressLayoutInner({ children, params: { address } }: Props) { infoStatus === FetchStatus.Fetched && infoParsed && isTokenProgramData(infoParsed) && pubkey ? ['get-full-token-info', address, cluster, url] : null, - fetchFullTokenInfo + fetchFullTokenInfo as BareFetcher ); // Fetch account on load @@ -271,77 +276,12 @@ function AccountHeader({ return ; } - if (isToken && !isTokenInfoLoading) { - let token: { logoURI?: string; name?: string } = {}; - let unverified = false; - - const metadataExtension = mintInfo?.extensions?.find( - ({ extension }: { extension: string }) => extension === 'tokenMetadata' - ); - const metadataPointerExtension = mintInfo?.extensions?.find( - ({ extension }: { extension: string }) => extension === 'metadataPointer' - ); - - if (metadataPointerExtension && metadataExtension) { - const tokenMetadata = create(metadataExtension.state, TokenMetadata); - const { metadataAddress } = create(metadataPointerExtension.state, MetadataPointer); - - // Handles the basic case where MetadataPointer is reference the Token Metadata extension directly - // Does not handle the case where MetadataPointer is pointing at a separate account. - if (metadataAddress?.toString() === address) { - token.name = tokenMetadata.name; - } - } - // Fall back to legacy token list when there is stub metadata (blank uri), updatable by default by the mint authority - else if (!parsedData?.nftData?.metadata.data.uri && tokenInfo) { - token = tokenInfo; - } else if (parsedData?.nftData) { - token = { - logoURI: parsedData?.nftData?.json?.image, - name: parsedData?.nftData?.json?.name ?? parsedData?.nftData.metadata.data.name, - }; - if (!tokenInfo?.verified) { - unverified = true; - } - } else if (tokenInfo) { - token = tokenInfo; - } - - return ( -
- {unverified && ( -
- Warning! Token names and logos are not unique. This token may have spoofed its name and logo to - look like another token. Verify the token's mint address to ensure it is correct. -
- )} -
-
- {token?.logoURI ? ( - // eslint-disable-next-line @next/next/no-img-element - token logo - ) : ( - - )} -
-
+ if (account && isNiftyAssetAccount(account.owner, account.data.raw)) { + return ; + } -
-
Token
-

{token?.name || 'Unknown Token'}

-
-
- ); + if (isToken && !isTokenInfoLoading) { + return ; } const fallback = ( @@ -362,6 +302,142 @@ function AccountHeader({ return fallback; } +function TokenMintHeader({ + address, + tokenInfo, + mintInfo, + parsedData, +}: { + address: string; + tokenInfo?: FullTokenInfo; + mintInfo?: MintAccountInfo; + parsedData?: TokenProgramData; +}): JSX.Element { + const metadataExtension = mintInfo?.extensions?.find( + ({ extension }: { extension: string }) => extension === 'tokenMetadata' + ); + const metadataPointerExtension = mintInfo?.extensions?.find( + ({ extension }: { extension: string }) => extension === 'metadataPointer' + ); + + const defaultCard = useMemo( + () => ( + + ), + [address, tokenInfo] + ); + + if (metadataPointerExtension && metadataExtension) { + return ( + <> + + + + + + + ); + } + // Fall back to legacy token list when there is stub metadata (blank uri), updatable by default by the mint authority + else if (!parsedData?.nftData?.metadata.data.uri && tokenInfo) { + return defaultCard; + } else if (parsedData?.nftData) { + const token = { + logoURI: parsedData?.nftData?.json?.image, + name: parsedData?.nftData?.json?.name ?? parsedData?.nftData.metadata.data.name, + }; + return ; + } else if (tokenInfo) { + return defaultCard; + } + return defaultCard; +} + +function Token22MintHeader({ + address, + metadataExtension, + metadataPointerExtension, +}: { + address: string; + metadataExtension: { extension: 'tokenMetadata'; state?: any }; + metadataPointerExtension: { extension: 'metadataPointer'; state?: any }; +}) { + const tokenMetadata = create(metadataExtension.state, TokenMetadata); + const { metadataAddress } = create(metadataPointerExtension.state, MetadataPointer); + const metadata = useMetadataJsonLink(tokenMetadata.uri, { suspense: true }); + + if (!metadata) { + throw new Error(`Could not load metadata from given URI: ${tokenMetadata.uri}`); + } + + // Handles the basic case where MetadataPointer is referencing the Token Metadata extension directly + // Does not handle the case where MetadataPointer is pointing at a separate account. + if (metadataAddress?.toString() === address) { + return ( + + ); + } + throw new Error('Metadata loading for non-token 2022 programs is not yet supported'); +} + +function TokenMintHeaderCard({ + address, + token, + unverified, +}: { + address: string; + token: { name?: string | undefined; logoURI?: string | undefined }; + unverified: boolean; +}) { + return ( +
+ {unverified && ( +
+ Warning! Token names and logos are not unique. This token may have spoofed its name and logo to look + like another token. Verify the token's mint address to ensure it is correct. +
+ )} +
+
+ {token?.logoURI ? ( + // eslint-disable-next-line @next/next/no-img-element + token logo + ) : ( + + )} +
+
+ +
+
Token
+

{token?.name || 'Unknown Token'}

+
+
+ ); +} + function DetailsSections({ children, pubkey, @@ -425,6 +501,8 @@ function InfoSection({ account, tokenInfo }: { account: Account; tokenInfo?: Ful ); } else if (account.owner.toBase58() === NFTOKEN_ADDRESS) { return ; + } else if (account.owner.toBase58() === ASSET_PROGRAM_ID) { + return ; } else if (parsedData && isTokenProgramData(parsedData)) { return ; } else if (parsedData && parsedData.program === 'nonce') { @@ -487,6 +565,9 @@ export type MoreTabs = | 'anchor-account' | 'entries' | 'concurrent-merkle-tree' + | 'nifty-asset-metadata' + | 'nifty-asset-extensions' + | 'nifty-asset-ruleset' | 'compression'; function MoreSection({ children, tabs }: { children: React.ReactNode; tabs: (JSX.Element | null)[] }) { @@ -573,8 +654,42 @@ function getTabs(pubkey: PublicKey, account: Account): TabComponent[] { } } + const isNiftyAsset = account && isNiftyAssetAccount(account.owner, account.data.raw); + if (isNiftyAsset && account.data.raw) { + const asset = account && (getInternalAssetAccountDataSerializer().deserialize(account.data.raw)[0] as Asset); + + if (asset.extensions.length > 0) { + const metadata = getExtension(asset, ExtensionType.Metadata); + + if (metadata && metadata.uri.length > 0) { + tabs.push({ + path: 'nifty-asset-metadata', + slug: 'nifty-asset-metadata', + title: 'Metadata', + }); + } + + const royalties = getExtension(asset, ExtensionType.Royalties); + + if (royalties && royalties.constraint.type !== 'Empty') { + tabs.push({ + path: 'nifty-asset-ruleset', + slug: 'nifty-asset-ruleset', + title: 'Rule Set', + }); + } + + tabs.push({ + path: 'nifty-asset-extensions', + slug: 'nifty-asset-extensions', + title: 'Extensions', + }); + } + } + if ( !isNFToken && + !isNiftyAsset && (!parsedData || !(TOKEN_TABS_HIDDEN.includes(parsedData.program) || TOKEN_TABS_HIDDEN.includes(programTypeKey))) ) { tabs.push({ diff --git a/app/address/[address]/metadata/page.tsx b/app/address/[address]/metadata/page.tsx index bb774ef3..e5c65282 100644 --- a/app/address/[address]/metadata/page.tsx +++ b/app/address/[address]/metadata/page.tsx @@ -11,8 +11,8 @@ type Props = Readonly<{ export async function generateMetadata(props: AddressPageMetadataProps): Promise { return { - description: `Metadata for the Metaplex NFT with address ${props.params.address} on Solana`, - title: `Metaplex NFT Metadata | ${await getReadableTitleFromAddress(props)} | Solana`, + description: `Metadata for the Metaplex NFT with address ${props.params.address} on Eclipse`, + title: `Metaplex NFT Metadata | ${await getReadableTitleFromAddress(props)} | Eclipse`, }; } diff --git a/app/address/[address]/nftoken-collection-nfts/page.tsx b/app/address/[address]/nftoken-collection-nfts/page.tsx index 3af85416..71bc2196 100644 --- a/app/address/[address]/nftoken-collection-nfts/page.tsx +++ b/app/address/[address]/nftoken-collection-nfts/page.tsx @@ -10,8 +10,8 @@ type Props = Readonly<{ export async function generateMetadata(props: AddressPageMetadataProps): Promise { return { - description: `NFToken NFTs belonging to the collection ${props.params.address} on Solana`, - title: `NFToken Collection NFTs | ${await getReadableTitleFromAddress(props)} | Solana`, + description: `NFToken NFTs belonging to the collection ${props.params.address} on Eclipse`, + title: `NFToken Collection NFTs | ${await getReadableTitleFromAddress(props)} | Eclipse`, }; } diff --git a/app/address/[address]/nifty-asset-extensions/page-client.tsx b/app/address/[address]/nifty-asset-extensions/page-client.tsx new file mode 100644 index 00000000..dbcbed95 --- /dev/null +++ b/app/address/[address]/nifty-asset-extensions/page-client.tsx @@ -0,0 +1,33 @@ +'use client'; + +import { ParsedAccountRenderer } from '@components/account/ParsedAccountRenderer'; +import { fromWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters'; +import { Asset, getInternalAssetAccountDataSerializer } from '@nifty-oss/asset'; +import React from 'react'; + +import { NiftyAssetExtensionsCard } from '@/app/components/account/nifty-asset/AssetExtensionsCard'; + +type Props = Readonly<{ + params: { + address: string; + }; +}>; + +function NiftyAssetExtensionsCardRenderer({ + account, + onNotFound, +}: React.ComponentProps['renderComponent']>) { + const data = account?.data.raw; + const address = account?.pubkey; + const asset = data && (getInternalAssetAccountDataSerializer().deserialize(data)[0] as Asset); + + if (asset && address) { + asset.publicKey = fromWeb3JsPublicKey(address); + } + + return asset && asset.extensions.length > 0 ? : onNotFound(); +} + +export default function MetaplexNFTMetadataPageClient({ params: { address } }: Props) { + return ; +} diff --git a/app/address/[address]/nifty-asset-extensions/page.tsx b/app/address/[address]/nifty-asset-extensions/page.tsx new file mode 100644 index 00000000..062f2ba3 --- /dev/null +++ b/app/address/[address]/nifty-asset-extensions/page.tsx @@ -0,0 +1,21 @@ +import getReadableTitleFromAddress, { AddressPageMetadataProps } from '@utils/get-readable-title-from-address'; +import { Metadata } from 'next/types'; + +import NiftyAssetExtensionsPageClient from './page-client'; + +type Props = Readonly<{ + params: { + address: string; + }; +}>; + +export async function generateMetadata(props: AddressPageMetadataProps): Promise { + return { + description: `Extensions for the asset with address ${props.params.address} on Solana`, + title: `Asset Extensions | ${await getReadableTitleFromAddress(props)} | Solana`, + }; +} + +export default function MetaplexNFTMetadataPage(props: Props) { + return ; +} diff --git a/app/address/[address]/nifty-asset-metadata/page-client.tsx b/app/address/[address]/nifty-asset-metadata/page-client.tsx new file mode 100644 index 00000000..c8e2e100 --- /dev/null +++ b/app/address/[address]/nifty-asset-metadata/page-client.tsx @@ -0,0 +1,35 @@ +'use client'; + +import { ParsedAccountRenderer } from '@components/account/ParsedAccountRenderer'; +import { Asset, ExtensionType, getExtension, getInternalAssetAccountDataSerializer } from '@nifty-oss/asset'; +import React from 'react'; + +import { NiftyAssetMetadataCard } from '@/app/components/account/nifty-asset/AssetMetadataCard'; + +type Props = Readonly<{ + params: { + address: string; + }; +}>; + +function NiftyAssetMetadataCardRenderer({ + account, + onNotFound, +}: React.ComponentProps['renderComponent']>) { + const data = account?.data.raw; + const asset = data && getInternalAssetAccountDataSerializer().deserialize(data); + + if (asset) { + const metadata = asset && getExtension(asset[0] as Asset, ExtensionType.Metadata); + + if (metadata && metadata.uri) { + return ; + } + } + + return onNotFound(); +} + +export default function MetaplexNFTMetadataPageClient({ params: { address } }: Props) { + return ; +} diff --git a/app/address/[address]/nifty-asset-metadata/page.tsx b/app/address/[address]/nifty-asset-metadata/page.tsx new file mode 100644 index 00000000..598e4428 --- /dev/null +++ b/app/address/[address]/nifty-asset-metadata/page.tsx @@ -0,0 +1,21 @@ +import getReadableTitleFromAddress, { AddressPageMetadataProps } from '@utils/get-readable-title-from-address'; +import { Metadata } from 'next/types'; + +import NiftyAssetMetadataPageClient from './page-client'; + +type Props = Readonly<{ + params: { + address: string; + }; +}>; + +export async function generateMetadata(props: AddressPageMetadataProps): Promise { + return { + description: `Metadata for the asset with address ${props.params.address} on Solana`, + title: `Asset Metadata | ${await getReadableTitleFromAddress(props)} | Solana`, + }; +} + +export default function MetaplexNFTMetadataPage(props: Props) { + return ; +} diff --git a/app/address/[address]/nifty-asset-ruleset/page-client.tsx b/app/address/[address]/nifty-asset-ruleset/page-client.tsx new file mode 100644 index 00000000..a417bbad --- /dev/null +++ b/app/address/[address]/nifty-asset-ruleset/page-client.tsx @@ -0,0 +1,31 @@ +'use client'; + +import { ParsedAccountRenderer } from '@components/account/ParsedAccountRenderer'; +import { Asset, ExtensionType, getExtension, getInternalAssetAccountDataSerializer } from '@nifty-oss/asset'; +import React from 'react'; + +import { NiftyAssetRuleSetCard } from '@/app/components/account/nifty-asset/AssetRuleSetCard'; + +type Props = Readonly<{ + params: { + address: string; + }; +}>; + +function NiftyAssetRuleSetCardRenderer({ + account, + onNotFound, +}: React.ComponentProps['renderComponent']>) { + const data = account?.data.raw; + const asset = data && (getInternalAssetAccountDataSerializer().deserialize(data)[0] as Asset); + + return asset && getExtension(asset, ExtensionType.Royalties) ? ( + + ) : ( + onNotFound() + ); +} + +export default function MetaplexNFTMetadataPageClient({ params: { address } }: Props) { + return ; +} diff --git a/app/address/[address]/nifty-asset-ruleset/page.tsx b/app/address/[address]/nifty-asset-ruleset/page.tsx new file mode 100644 index 00000000..544a5bd5 --- /dev/null +++ b/app/address/[address]/nifty-asset-ruleset/page.tsx @@ -0,0 +1,21 @@ +import getReadableTitleFromAddress, { AddressPageMetadataProps } from '@utils/get-readable-title-from-address'; +import { Metadata } from 'next/types'; + +import NiftyAssetRuleSetPageClient from './page-client'; + +type Props = Readonly<{ + params: { + address: string; + }; +}>; + +export async function generateMetadata(props: AddressPageMetadataProps): Promise { + return { + description: `Royalties Rule Set for the asset with address ${props.params.address} on Solana`, + title: `Rule Set for Asset | ${await getReadableTitleFromAddress(props)} | Solana`, + }; +} + +export default function MetaplexNFTMetadataPage(props: Props) { + return ; +} diff --git a/app/address/[address]/page.tsx b/app/address/[address]/page.tsx index 8d40fda0..59e1f918 100644 --- a/app/address/[address]/page.tsx +++ b/app/address/[address]/page.tsx @@ -10,8 +10,8 @@ type Props = Readonly<{ export async function generateMetadata(props: AddressPageMetadataProps): Promise { return { - description: `History of all transactions involving the address ${props.params.address} on Solana`, - title: `Transaction History | ${await getReadableTitleFromAddress(props)} | Solana`, + description: `History of all transactions involving the address ${props.params.address} on Eclipse`, + title: `Transaction History | ${await getReadableTitleFromAddress(props)} | Eclipse`, }; } diff --git a/app/address/[address]/rewards/page.tsx b/app/address/[address]/rewards/page.tsx index aef49b67..a03eddc3 100644 --- a/app/address/[address]/rewards/page.tsx +++ b/app/address/[address]/rewards/page.tsx @@ -10,8 +10,8 @@ type Props = Readonly<{ export async function generateMetadata(props: AddressPageMetadataProps): Promise { return { - description: `Rewards due to the address ${props.params.address} by epoch on Solana`, - title: `Address Rewards | ${await getReadableTitleFromAddress(props)} | Solana`, + description: `Rewards due to the address ${props.params.address} by epoch on Eclipse`, + title: `Address Rewards | ${await getReadableTitleFromAddress(props)} | Eclipse`, }; } diff --git a/app/address/[address]/security/page.tsx b/app/address/[address]/security/page.tsx index acf53198..94276108 100644 --- a/app/address/[address]/security/page.tsx +++ b/app/address/[address]/security/page.tsx @@ -5,8 +5,8 @@ import SecurityPageClient from './page-client'; export async function generateMetadata(props: AddressPageMetadataProps): Promise { return { - description: `Contents of the security.txt for the program with address ${props.params.address} on Solana`, - title: `Security | ${await getReadableTitleFromAddress(props)} | Solana`, + description: `Contents of the security.txt for the program with address ${props.params.address} on Eclipse`, + title: `Security | ${await getReadableTitleFromAddress(props)} | Eclipse`, }; } diff --git a/app/address/[address]/slot-hashes/page.tsx b/app/address/[address]/slot-hashes/page.tsx index 9b3ea653..ca85947e 100644 --- a/app/address/[address]/slot-hashes/page.tsx +++ b/app/address/[address]/slot-hashes/page.tsx @@ -7,8 +7,8 @@ type Props = Readonly<{ }>; export const metadata = { - description: `Hashes of each slot on Solana`, - title: `Slot Hashes | Solana`, + description: `Hashes of each slot on Eclipse`, + title: `Slot Hashes | Eclipse`, }; export default function SlotHashesPage(props: Props) { diff --git a/app/address/[address]/stake-history/page.tsx b/app/address/[address]/stake-history/page.tsx index f48227b8..e418a3d0 100644 --- a/app/address/[address]/stake-history/page.tsx +++ b/app/address/[address]/stake-history/page.tsx @@ -7,8 +7,8 @@ type Props = Readonly<{ }>; export const metadata = { - description: `Stake history for each epoch on Solana`, - title: `Stake History | Solana`, + description: `Stake history for each epoch on Eclipse`, + title: `Stake History | Eclipse`, }; export default function StakeHistoryPage(props: Props) { diff --git a/app/address/[address]/tokens/page.tsx b/app/address/[address]/tokens/page.tsx index 7a43d450..b3a6d3a0 100644 --- a/app/address/[address]/tokens/page.tsx +++ b/app/address/[address]/tokens/page.tsx @@ -13,8 +13,8 @@ type Props = Readonly<{ export async function generateMetadata(props: AddressPageMetadataProps): Promise { return { - description: `All tokens owned by the address ${props.params.address} on Solana`, - title: `Tokens | ${await getReadableTitleFromAddress(props)} | Solana`, + description: `All tokens owned by the address ${props.params.address} on Eclipse`, + title: `Tokens | ${await getReadableTitleFromAddress(props)} | Eclipse`, }; } diff --git a/app/address/[address]/transfers/page.tsx b/app/address/[address]/transfers/page.tsx index 8fd0c8ec..52cc43e1 100644 --- a/app/address/[address]/transfers/page.tsx +++ b/app/address/[address]/transfers/page.tsx @@ -10,8 +10,8 @@ type Props = Readonly<{ export async function generateMetadata(props: AddressPageMetadataProps): Promise { return { - description: `History of all token transfers involving the address ${props.params.address} on Solana`, - title: `Transfers | ${await getReadableTitleFromAddress(props)} | Solana`, + description: `History of all token transfers involving the address ${props.params.address} on Eclipse`, + title: `Transfers | ${await getReadableTitleFromAddress(props)} | Eclipse`, }; } diff --git a/app/address/[address]/vote-history/page.tsx b/app/address/[address]/vote-history/page.tsx index ff6c34b9..01a4f8af 100644 --- a/app/address/[address]/vote-history/page.tsx +++ b/app/address/[address]/vote-history/page.tsx @@ -11,8 +11,8 @@ type Props = Readonly<{ export async function generateMetadata(props: AddressPageMetadataProps): Promise { return { - description: `Vote history of the address ${props.params.address} by slot on Solana`, - title: `Vote History | ${await getReadableTitleFromAddress(props)} | Solana`, + description: `Vote history of the address ${props.params.address} by slot on Eclipse`, + title: `Vote History | ${await getReadableTitleFromAddress(props)} | Eclipse`, }; } diff --git a/app/api/domain-info/[domain]/route.ts b/app/api/domain-info/[domain]/route.ts index a5d3759a..7d698df4 100644 --- a/app/api/domain-info/[domain]/route.ts +++ b/app/api/domain-info/[domain]/route.ts @@ -1,31 +1,25 @@ -import { Connection } from "@solana/web3.js" -import { NextResponse } from "next/server" +import { Connection } from "@solana/web3.js"; +import { NextResponse } from "next/server"; -import { MAINNET_BETA_URL } from "@/app/utils/cluster" -import { getDomainInfo } from "@/app/utils/domain-info" +import { MAINNET_BETA_URL } from "@/app/utils/cluster"; +import { getANSDomainInfo } from "@/app/utils/domain-info"; type Params = { params: { - domain: string - } -} + domain: string; + }; +}; -export type FetchedDomainInfo = Awaited>; +export type FetchedDomainInfo = Awaited>; -export async function GET( - _request: Request, - { params: { domain } }: Params -) { - // Intentionally using legacy web3js for compatibility with bonfida library - // This is an API route so won't affect client bundle - // We only fetch domains on mainnet +export async function GET(_request: Request, { params: { domain } }: Params) { const connection = new Connection(MAINNET_BETA_URL); - const domainInfo = await getDomainInfo(domain, connection); + const domainInfo = await (getANSDomainInfo(domain, connection)) return NextResponse.json(domainInfo, { headers: { // 24 hours - "Cache-Control": "max-age=86400" - } + "Cache-Control": "max-age=86400", + }, }); } diff --git a/app/apple-icon.png b/app/apple-icon.png old mode 100755 new mode 100644 index 0f746f3c..534f5cc5 Binary files a/app/apple-icon.png and b/app/apple-icon.png differ diff --git a/app/block/[slot]/accounts/page.tsx b/app/block/[slot]/accounts/page.tsx index eb49d39e..5d4e1c35 100644 --- a/app/block/[slot]/accounts/page.tsx +++ b/app/block/[slot]/accounts/page.tsx @@ -10,8 +10,8 @@ type Props = Readonly<{ export async function generateMetadata({ params: { slot } }: Props): Promise { return { - description: `Statistics pertaining to accounts which were accessed or written to during block ${slot} on Solana`, - title: `Accounts Active In Block | ${slot} | Solana`, + description: `Statistics pertaining to accounts which were accessed or written to during block ${slot} on Eclipse`, + title: `Accounts Active In Block | ${slot} | Eclipse`, }; } diff --git a/app/block/[slot]/page.tsx b/app/block/[slot]/page.tsx index 3ba85e25..320f8da8 100644 --- a/app/block/[slot]/page.tsx +++ b/app/block/[slot]/page.tsx @@ -10,8 +10,8 @@ type Props = Readonly<{ export async function generateMetadata({ params: { slot } }: Props): Promise { return { - description: `History of all transactions during block ${slot} on Solana`, - title: `Block | ${slot} | Solana`, + description: `History of all transactions during block ${slot} on Eclipse`, + title: `Block | ${slot} | Eclipse`, }; } diff --git a/app/block/[slot]/programs/page.tsx b/app/block/[slot]/programs/page.tsx index 8a772b70..600ea730 100644 --- a/app/block/[slot]/programs/page.tsx +++ b/app/block/[slot]/programs/page.tsx @@ -10,8 +10,8 @@ type Props = Readonly<{ export async function generateMetadata({ params: { slot } }: Props): Promise { return { - description: `Statistics pertaining to programs which were active during block ${slot} on Solana`, - title: `Programs Active In Block | ${slot} | Solana`, + description: `Statistics pertaining to programs which were active during block ${slot} on Eclipse`, + title: `Programs Active In Block | ${slot} | Eclipse`, }; } diff --git a/app/block/[slot]/rewards/page.tsx b/app/block/[slot]/rewards/page.tsx index 8503f2d4..307040ff 100644 --- a/app/block/[slot]/rewards/page.tsx +++ b/app/block/[slot]/rewards/page.tsx @@ -10,8 +10,8 @@ type Props = Readonly<{ export async function generateMetadata({ params: { slot } }: Props): Promise { return { - description: `List of addresses to which rewards were disbursed during block ${slot} on Solana`, - title: `Block Rewards | ${slot} | Solana`, + description: `List of addresses to which rewards were disbursed during block ${slot} on Eclipse`, + title: `Block Rewards | ${slot} | Eclipse`, }; } diff --git a/app/components/Navbar.tsx b/app/components/Navbar.tsx index e9c95f22..0cfbcf6b 100644 --- a/app/components/Navbar.tsx +++ b/app/components/Navbar.tsx @@ -1,6 +1,6 @@ 'use client'; -import Logo from '@img/logos-solana/dark-explorer-logo.svg'; +import Logo from '@img/logos-eclipse/Eclipse_logo_lockup_white.svg'; import { useClusterPath } from '@utils/url'; import Image from 'next/image'; import Link from 'next/link'; @@ -21,7 +21,7 @@ export function Navbar() {