import React from "react";
import { useClusterModal } from "providers/cluster";
import { PublicKey, StakeProgram } from "@solana/web3.js";
import ClusterStatusButton from "components/ClusterStatusButton";
import { useHistory, useLocation } from "react-router-dom";
import {
Status,
useFetchAccountInfo,
useFetchAccountHistory,
useAccountInfo,
Account
} from "providers/accounts";
import { lamportsToSolString } from "utils";
import Copyable from "./Copyable";
import { displayAddress } from "utils/tx";
import { StakeAccountCards } from "components/account/StakeAccountCards";
import ErrorCard from "components/common/ErrorCard";
import LoadingCard from "components/common/LoadingCard";
import TableCardBody from "components/common/TableCardBody";
type Props = { address: string };
export default function AccountDetails({ address }: Props) {
const fetchAccount = useFetchAccountInfo();
const [, setShow] = useClusterModal();
const [search, setSearch] = React.useState(address);
const history = useHistory();
const location = useLocation();
let pubkey: PublicKey | undefined;
try {
pubkey = new PublicKey(address);
} catch (err) {
console.error(err);
// TODO handle bad addresses
}
const updateAddress = () => {
history.push({ ...location, pathname: "/account/" + search });
};
// Fetch account on load
React.useEffect(() => {
if (pubkey) fetchAccount(pubkey);
}, [pubkey?.toBase58()]); // eslint-disable-line react-hooks/exhaustive-deps
const searchInput = (
setSearch(e.target.value)}
onKeyUp={e => e.key === "Enter" && updateAddress()}
className="form-control form-control-prepended search text-monospace"
placeholder="Search for address"
/>
);
return (
Details
Account
setShow(true)} />
{pubkey &&
}
{pubkey &&
}
);
}
function AccountCards({ pubkey }: { pubkey: PublicKey }) {
const address = pubkey.toBase58();
const info = useAccountInfo(address);
const refresh = useFetchAccountInfo();
if (!info || info.status === Status.Checking) {
return ;
} else if (
info.status === Status.CheckFailed ||
info.lamports === undefined
) {
return refresh(pubkey)} text="Fetch Failed" />;
}
const owner = info.details?.owner;
const data = info.details?.data;
if (data && owner && owner.equals(StakeProgram.programId)) {
return ;
} else {
return ;
}
}
function UnknownAccountCard({ account }: { account: Account }) {
const refresh = useFetchAccountInfo();
const { details, lamports, pubkey } = account;
if (lamports === undefined) return null;
return (
Account Overview
Balance (SOL) |
{lamportsToSolString(lamports)}
|
{details && (
Data (Bytes) |
{details.space} |
)}
{details && (
Owner |
{displayAddress(details.owner.toBase58())}
|
)}
{details && (
Executable |
{details.executable ? "Yes" : "No"} |
)}
);
}
function HistoryCard({ pubkey }: { pubkey: PublicKey }) {
const address = pubkey.toBase58();
const info = useAccountInfo(address);
const refresh = useFetchAccountHistory();
if (!info || !info.details) {
return null;
} else if (info.status === Status.FetchingHistory) {
return ;
} else if (info.history === undefined) {
return (
refresh(pubkey)}
text="Failed to fetch transaction history"
/>
);
}
if (info.history.size === 0) {
return (
refresh(pubkey)}
text="No recent transaction history found"
/>
);
}
const detailsList: React.ReactNode[] = [];
info.history.forEach((slotTransactions, slot) => {
const signatures = Array.from(slotTransactions.entries()).map(
([signature, err]) => {
return {signature}
;
}
);
detailsList.push(
Slot {slot} |
{signatures}
|
);
});
return (
Transaction History
{detailsList}
);
}