From 3e2538919f8cfdab028f4f7ce3f6e889820468ac Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Thu, 14 May 2020 23:20:35 +0800 Subject: [PATCH] Spruce up stake account details page --- explorer/src/components/AccountDetails.tsx | 68 ++---- .../components/account/StakeAccountCards.tsx | 198 ++++++++++++++++++ .../account/StakeAccountDetailsCard.tsx | 121 ----------- explorer/src/providers/accounts.tsx | 11 +- 4 files changed, 227 insertions(+), 171 deletions(-) create mode 100644 explorer/src/components/account/StakeAccountCards.tsx delete mode 100644 explorer/src/components/account/StakeAccountDetailsCard.tsx diff --git a/explorer/src/components/AccountDetails.tsx b/explorer/src/components/AccountDetails.tsx index 616657ecd5..d9d95dedf5 100644 --- a/explorer/src/components/AccountDetails.tsx +++ b/explorer/src/components/AccountDetails.tsx @@ -1,5 +1,4 @@ import React from "react"; -import { StakeAccount } from "solana-sdk-wasm"; import { useClusterModal } from "providers/cluster"; import { PublicKey, StakeProgram } from "@solana/web3.js"; import ClusterStatusButton from "components/ClusterStatusButton"; @@ -8,12 +7,13 @@ import { Status, useFetchAccountInfo, useFetchAccountHistory, - useAccountInfo + useAccountInfo, + Account } from "providers/accounts"; import { lamportsToSolString } from "utils"; import Copyable from "./Copyable"; import { displayAddress } from "utils/tx"; -import { StakeAccountDetailsCard } from "components/account/StakeAccountDetailsCard"; +import { StakeAccountCards } from "components/account/StakeAccountCards"; import ErrorCard from "components/common/ErrorCard"; import LoadingCard from "components/common/LoadingCard"; import TableCardBody from "components/common/TableCardBody"; @@ -88,54 +88,13 @@ export default function AccountDetails({ address }: Props) { - {pubkey && } - {pubkey && } + {pubkey && } {pubkey && } ); } -type Wasm = { - StakeAccount: typeof StakeAccount; -}; - -function DetailsCard({ pubkey }: { pubkey: PublicKey }) { - const address = pubkey.toBase58(); - const info = useAccountInfo(address); - const [Wasm, setWasm] = React.useState(undefined); - - React.useEffect(() => { - (async () => { - try { - setWasm(await import("solana-sdk-wasm")); - } catch (err) { - console.error("Unexpected error loading wasm", err); - } - })(); - }, []); - - if (!info || !info.details || !info.details.data) { - return null; - } - - const { data, owner } = info.details; - try { - if (owner.equals(StakeProgram.programId)) { - if (Wasm === undefined) { - return ; - } else { - const stakeAccount = Wasm.StakeAccount.fromAccountData(data); - return ; - } - } - } catch (err) { - console.error(err); - return ; - } - return null; -} - -function InfoCard({ pubkey }: { pubkey: PublicKey }) { +function AccountCards({ pubkey }: { pubkey: PublicKey }) { const address = pubkey.toBase58(); const info = useAccountInfo(address); const refresh = useFetchAccountInfo(); @@ -149,12 +108,25 @@ function InfoCard({ pubkey }: { pubkey: PublicKey }) { return refresh(pubkey)} text="Fetch Failed" />; } - const { details, lamports } = info; + 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 (
-

Overview

+

Account Overview

+
+ + + + Address + + + {account.pubkey.toBase58()} + + + + + Balance (SOL) + + {lamportsToSolString(account.lamports || 0)} + + + {stakeAccount.meta && ( + + Rent Reserve (SOL) + + {lamportsToSolString(stakeAccount.meta.rentExemptReserve)} + + + )} + {!stakeAccount.meta && ( + + State + {stakeAccount.displayState()} + + )} + +
+ ); +} + +function DelegationCard({ stakeAccount }: { stakeAccount: StakeAccount }) { + const { stake } = stakeAccount; + return ( +
+
+

+ Stake Delegation +

+
+ + + Status + {stakeAccount.displayState()} + + + {stake && ( + <> + + Delegated Stake (SOL) + + {lamportsToSolString(stake.delegation.stake)} + + + + + Delegated Vote Address + + + + {displayAddress(stake.delegation.voterPubkey.toBase58())} + + + + + + + Activation Epoch + + {stake.delegation.isBootstrapStake() + ? "-" + : stake.delegation.activationEpoch} + + + + + Deactivation Epoch + + {stake.delegation.isDeactivated() + ? stake.delegation.deactivationEpoch + : "-"} + + + + )} + +
+ ); +} + +function AuthoritiesCard({ meta }: { meta: Meta }) { + const hasLockup = meta && meta.lockup.unixTimestamp > 0; + return ( +
+
+

+ Authorities +

+
+ + + Stake Authority Address + + + {meta.authorized.staker.toBase58()} + + + + + + Withdraw Authority Address + + + {meta.authorized.withdrawer.toBase58()} + + + + + {hasLockup && ( + + Lockup Authority Address + + + {displayAddress(meta.lockup.custodian.toBase58())} + + + + )} + +
+ ); +} diff --git a/explorer/src/components/account/StakeAccountDetailsCard.tsx b/explorer/src/components/account/StakeAccountDetailsCard.tsx deleted file mode 100644 index c7defe6ea8..0000000000 --- a/explorer/src/components/account/StakeAccountDetailsCard.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import React from "react"; -import { StakeAccount } from "solana-sdk-wasm"; -import TableCardBody from "components/common/TableCardBody"; -import { lamportsToSolString } from "utils"; -import Copyable from "components/Copyable"; -import { displayAddress } from "utils/tx"; - -export function StakeAccountDetailsCard({ - account -}: { - account: StakeAccount; -}) { - const { meta, stake } = account; - const hasLockup = meta && meta.lockup.unixTimestamp > 0; - return ( -
-
-

- Stake Account -

-
- - - State - {account.displayState()} - - - {meta && ( - <> - - Rent Reserve (SOL) - - {lamportsToSolString(meta.rentExemptReserve)} - - - - - Stake Authority Address - - - {meta.authorized.staker.toBase58()} - - - - - - Withdraw Authority Address - - - {meta.authorized.withdrawer.toBase58()} - - - - - {hasLockup && ( - - Lockup Expiry Timestamp - - {new Date(meta.lockup.unixTimestamp).toUTCString()} - - - )} - - {hasLockup && ( - - Lockup Custodian Address - - - - {displayAddress(meta.lockup.custodian.toBase58())} - - - - - )} - - )} - - {stake && ( - <> - - Delegated Stake (SOL) - - {lamportsToSolString(stake.delegation.stake)} - - - - - Delegated Vote Address - - - - {displayAddress(stake.delegation.voterPubkey.toBase58())} - - - - - - - Activation Epoch - - {stake.delegation.isBootstrapStake() - ? "-" - : stake.delegation.activationEpoch} - - - - - Deactivation Epoch - - {stake.delegation.isDeactivated() - ? stake.delegation.deactivationEpoch - : "-"} - - - - )} - -
- ); -} diff --git a/explorer/src/providers/accounts.tsx b/explorer/src/providers/accounts.tsx index 47c0e9abaf..88a7b9966f 100644 --- a/explorer/src/providers/accounts.tsx +++ b/explorer/src/providers/accounts.tsx @@ -9,6 +9,7 @@ import { } from "@solana/web3.js"; import { useQuery } from "../utils/url"; import { useCluster, ClusterStatus } from "./cluster"; +import { StakeAccount } from "solana-sdk-wasm"; export enum Status { Checking, @@ -28,7 +29,7 @@ export interface Details { executable: boolean; owner: PublicKey; space: number; - data?: Buffer; + data?: StakeAccount; } export interface Account { @@ -198,7 +199,13 @@ async function fetchAccountInfo( // Only save data in memory if we can decode it if (result.owner.equals(StakeProgram.programId)) { - data = result.data; + try { + const wasm = await import("solana-sdk-wasm"); + data = wasm.StakeAccount.fromAccountData(result.data); + } catch (err) { + console.error("Unexpected error loading wasm", err); + // TODO store error state in Account info + } } details = {