2020-08-07 23:45:57 -07:00
|
|
|
import React from "react";
|
2020-08-08 08:02:01 -07:00
|
|
|
import { PublicKey } from "@solana/web3.js";
|
2020-08-12 07:41:04 -07:00
|
|
|
import { FetchStatus } from "providers/cache";
|
|
|
|
import { useFetchAccountInfo, useAccountInfo } from "providers/accounts";
|
2020-08-07 23:45:57 -07:00
|
|
|
import { StakeAccountSection } from "components/account/StakeAccountSection";
|
2020-08-08 08:02:01 -07:00
|
|
|
import { TokenAccountSection } from "components/account/TokenAccountSection";
|
2020-08-07 23:45:57 -07:00
|
|
|
import { ErrorCard } from "components/common/ErrorCard";
|
|
|
|
import { LoadingCard } from "components/common/LoadingCard";
|
|
|
|
import { useCluster, ClusterStatus } from "providers/cluster";
|
|
|
|
import { NavLink } 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";
|
2020-08-08 09:29:42 -07:00
|
|
|
import { TokenHistoryCard } from "components/account/TokenHistoryCard";
|
2020-08-07 23:45:57 -07:00
|
|
|
|
|
|
|
type Props = { address: string; tab?: string };
|
|
|
|
export function AccountDetailsPage({ address, tab }: Props) {
|
|
|
|
let pubkey: PublicKey | undefined;
|
|
|
|
try {
|
|
|
|
pubkey = new PublicKey(address);
|
|
|
|
} catch (err) {
|
|
|
|
console.error(err);
|
|
|
|
// TODO handle bad addresses
|
|
|
|
}
|
|
|
|
|
|
|
|
let moreTab: MoreTabs = "history";
|
|
|
|
if (tab === "history" || tab === "tokens") {
|
|
|
|
moreTab = tab;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="container mt-n3">
|
|
|
|
<div className="header">
|
|
|
|
<div className="header-body">
|
|
|
|
<h6 className="header-pretitle">Details</h6>
|
|
|
|
<h4 className="header-title">Account</h4>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{pubkey && <InfoSection pubkey={pubkey} />}
|
|
|
|
{pubkey && <MoreSection pubkey={pubkey} tab={moreTab} />}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function InfoSection({ pubkey }: { pubkey: PublicKey }) {
|
|
|
|
const fetchAccount = useFetchAccountInfo();
|
|
|
|
const address = pubkey.toBase58();
|
|
|
|
const info = useAccountInfo(address);
|
|
|
|
const refresh = useFetchAccountInfo();
|
|
|
|
const { status } = useCluster();
|
|
|
|
|
|
|
|
// 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 <LoadingCard />;
|
|
|
|
} else if (
|
|
|
|
info.status === FetchStatus.FetchFailed ||
|
2020-08-12 07:41:04 -07:00
|
|
|
info.data?.lamports === undefined
|
2020-08-07 23:45:57 -07:00
|
|
|
) {
|
|
|
|
return <ErrorCard retry={() => refresh(pubkey)} text="Fetch Failed" />;
|
|
|
|
}
|
|
|
|
|
2020-08-12 07:41:04 -07:00
|
|
|
const account = info.data;
|
|
|
|
const data = account?.details?.data;
|
2020-08-08 08:02:01 -07:00
|
|
|
if (data && data.name === "stake") {
|
2020-08-08 06:06:24 -07:00
|
|
|
let stakeAccountType, stakeAccount;
|
2020-08-08 08:02:01 -07:00
|
|
|
if ("accountType" in data.parsed) {
|
|
|
|
stakeAccount = data.parsed;
|
|
|
|
stakeAccountType = data.parsed.accountType as any;
|
2020-08-08 06:06:24 -07:00
|
|
|
} else {
|
2020-08-08 08:02:01 -07:00
|
|
|
stakeAccount = data.parsed.info;
|
|
|
|
stakeAccountType = data.parsed.type;
|
2020-08-08 06:06:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<StakeAccountSection
|
2020-08-12 07:41:04 -07:00
|
|
|
account={account}
|
2020-08-08 06:06:24 -07:00
|
|
|
stakeAccount={stakeAccount}
|
|
|
|
stakeAccountType={stakeAccountType}
|
|
|
|
/>
|
|
|
|
);
|
2020-08-08 08:02:01 -07:00
|
|
|
} else if (data && data.name === "spl-token") {
|
2020-08-12 07:41:04 -07:00
|
|
|
return <TokenAccountSection account={account} tokenAccount={data.parsed} />;
|
2020-08-07 23:45:57 -07:00
|
|
|
} else {
|
2020-08-12 07:41:04 -07:00
|
|
|
return <UnknownAccountCard account={account} />;
|
2020-08-07 23:45:57 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type MoreTabs = "history" | "tokens";
|
|
|
|
function MoreSection({ pubkey, tab }: { pubkey: PublicKey; tab: MoreTabs }) {
|
|
|
|
const address = pubkey.toBase58();
|
|
|
|
const info = useAccountInfo(address);
|
2020-08-12 07:41:04 -07:00
|
|
|
if (info?.data === undefined) return null;
|
2020-08-07 23:45:57 -07:00
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<div className="container">
|
|
|
|
<div className="header">
|
|
|
|
<div className="header-body pt-0">
|
|
|
|
<ul className="nav nav-tabs nav-overflow header-tabs">
|
|
|
|
<li className="nav-item">
|
|
|
|
<NavLink
|
|
|
|
className="nav-link"
|
|
|
|
to={clusterPath(`/address/${address}`)}
|
|
|
|
exact
|
|
|
|
>
|
|
|
|
History
|
|
|
|
</NavLink>
|
|
|
|
</li>
|
|
|
|
<li className="nav-item">
|
|
|
|
<NavLink
|
|
|
|
className="nav-link"
|
|
|
|
to={clusterPath(`/address/${address}/tokens`)}
|
|
|
|
exact
|
|
|
|
>
|
|
|
|
Tokens
|
|
|
|
</NavLink>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2020-08-08 09:29:42 -07:00
|
|
|
{tab === "tokens" && (
|
|
|
|
<>
|
|
|
|
<OwnedTokensCard pubkey={pubkey} />
|
|
|
|
<TokenHistoryCard pubkey={pubkey} />
|
|
|
|
</>
|
|
|
|
)}
|
2020-08-07 23:45:57 -07:00
|
|
|
{tab === "history" && <TransactionHistoryCard pubkey={pubkey} />}
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|