import React from "react"; import { PublicKey } from "@solana/web3.js"; import { FetchStatus } from "providers/cache"; import { useFetchAccountInfo, useAccountInfo, Account, ProgramData, } from "providers/accounts"; import { StakeAccountSection } from "components/account/StakeAccountSection"; import { TokenAccountSection } from "components/account/TokenAccountSection"; import { ErrorCard } from "components/common/ErrorCard"; import { LoadingCard } from "components/common/LoadingCard"; import { useCluster, ClusterStatus } from "providers/cluster"; import { NavLink, Redirect, useLocation } from "react-router-dom"; import { clusterPath } from "utils/url"; import { UnknownAccountCard } from "components/account/UnknownAccountCard"; import { OwnedTokensCard } from "components/account/OwnedTokensCard"; import { TransactionHistoryCard } from "components/account/TransactionHistoryCard"; import { TokenHistoryCard } from "components/account/TokenHistoryCard"; import { TokenLargestAccountsCard } from "components/account/TokenLargestAccountsCard"; import { VoteAccountSection } from "components/account/VoteAccountSection"; import { NonceAccountSection } from "components/account/NonceAccountSection"; import { VotesCard } from "components/account/VotesCard"; import { SysvarAccountSection } from "components/account/SysvarAccountSection"; import { SlotHashesCard } from "components/account/SlotHashesCard"; import { StakeHistoryCard } from "components/account/StakeHistoryCard"; import { BlockhashesCard } from "components/account/BlockhashesCard"; import { ConfigAccountSection } from "components/account/ConfigAccountSection"; import { useFlaggedAccounts } from "providers/accounts/flagged-accounts"; import { UpgradeableProgramSection } from "components/account/UpgradeableProgramSection"; import { useTokenRegistry } from "providers/mints/token-registry"; const TABS_LOOKUP: { [id: string]: Tab } = { "spl-token:mint": { slug: "largest", title: "Distribution", path: "/largest", }, vote: { slug: "vote-history", title: "Vote History", path: "/vote-history", }, "sysvar:recentBlockhashes": { slug: "blockhashes", title: "Blockhashes", path: "/blockhashes", }, "sysvar:slotHashes": { slug: "slot-hashes", title: "Slot Hashes", path: "/slot-hashes", }, "sysvar:stakeHistory": { slug: "stake-history", title: "Stake History", path: "/stake-history", }, }; const TOKEN_TABS_HIDDEN = [ "spl-token:mint", "config", "vote", "sysvar", "config", ]; type Props = { address: string; tab?: string }; export function AccountDetailsPage({ address, tab }: Props) { let pubkey: PublicKey | undefined; try { pubkey = new PublicKey(address); } catch (err) {} return (
{!pubkey ? ( ) : ( )}
); } export function AccountHeader({ address }: { address: string }) { const { tokenRegistry } = useTokenRegistry(); const tokenDetails = tokenRegistry.get(address); if (tokenDetails) { return (
{tokenDetails.icon && (
token logo
)}
Token

{tokenDetails.tokenName}

); } return ( <>
Details

Account

); } function DetailsSections({ pubkey, tab }: { pubkey: PublicKey; tab?: string }) { const fetchAccount = useFetchAccountInfo(); const address = pubkey.toBase58(); const info = useAccountInfo(address); const { status } = useCluster(); const location = useLocation(); const { flaggedAccounts } = useFlaggedAccounts(); // Fetch account on load React.useEffect(() => { if (!info && status === ClusterStatus.Connected) fetchAccount(pubkey); }, [address, status]); // eslint-disable-line react-hooks/exhaustive-deps if (!info || info.status === FetchStatus.Fetching) { return ; } else if ( info.status === FetchStatus.FetchFailed || info.data?.lamports === undefined ) { return fetchAccount(pubkey)} text="Fetch Failed" />; } const account = info.data; const data = account?.details?.data; const tabs = getTabs(data); let moreTab: MoreTabs = "history"; if (tab && tabs.filter(({ slug }) => slug === tab).length === 0) { return ; } else if (tab) { moreTab = tab as MoreTabs; } return ( <> {flaggedAccounts.has(address) && (
Warning! This account has been flagged by the community as a scam account. Please be cautious sending SOL to this account.
)} {} {} ); } function InfoSection({ account }: { account: Account }) { const data = account?.details?.data; if (data && data.program === "bpf-upgradeable-loader") { return ( ); } else if (data && data.program === "stake") { return ( ); } else if (data && data.program === "spl-token") { return ; } else if (data && data.program === "nonce") { return ; } else if (data && data.program === "vote") { return ; } else if (data && data.program === "sysvar") { return ( ); } else if (data && data.program === "config") { return ( ); } else { return ; } } type Tab = { slug: MoreTabs; title: string; path: string; }; type MoreTabs = | "history" | "tokens" | "largest" | "vote-history" | "slot-hashes" | "stake-history" | "blockhashes"; function MoreSection({ account, tab, tabs, }: { account: Account; tab: MoreTabs; tabs: Tab[]; }) { const pubkey = account.pubkey; const address = account.pubkey.toBase58(); const data = account?.details?.data; return ( <>
    {tabs.map(({ title, slug, path }) => (
  • {title}
  • ))}
{tab === "tokens" && ( <> )} {tab === "history" && } {tab === "largest" && } {tab === "vote-history" && data?.program === "vote" && ( )} {tab === "slot-hashes" && data?.program === "sysvar" && data.parsed.type === "slotHashes" && ( )} {tab === "stake-history" && data?.program === "sysvar" && data.parsed.type === "stakeHistory" && ( )} {tab === "blockhashes" && data?.program === "sysvar" && data.parsed.type === "recentBlockhashes" && ( )} ); } function getTabs(data?: ProgramData): Tab[] { const tabs: Tab[] = [ { slug: "history", title: "History", path: "", }, ]; let programTypeKey = ""; if (data && "parsed" in data && "type" in data.parsed) { programTypeKey = `${data.program}:${data.parsed.type}`; } if (data && data.program in TABS_LOOKUP) { tabs.push(TABS_LOOKUP[data.program]); } if (data && programTypeKey in TABS_LOOKUP) { tabs.push(TABS_LOOKUP[programTypeKey]); } if ( !data || !( TOKEN_TABS_HIDDEN.includes(data.program) || TOKEN_TABS_HIDDEN.includes(programTypeKey) ) ) { tabs.push({ slug: "tokens", title: "Tokens", path: "/tokens", }); } return tabs; }