diff --git a/explorer/src/components/account/UpgradeableProgramSection.tsx b/explorer/src/components/account/UpgradeableProgramSection.tsx
new file mode 100644
index 0000000000..df2858e9a6
--- /dev/null
+++ b/explorer/src/components/account/UpgradeableProgramSection.tsx
@@ -0,0 +1,83 @@
+import React from "react";
+import { TableCardBody } from "components/common/TableCardBody";
+import { lamportsToSolString } from "utils";
+import { Account, useFetchAccountInfo } from "providers/accounts";
+import { Address } from "components/common/Address";
+import {
+ ProgramAccountInfo,
+ ProgramDataAccountInfo,
+} from "validators/accounts/upgradeable-program";
+import { Slot } from "components/common/Slot";
+
+export function UpgradeableProgramSection({
+ account,
+ programAccount,
+ programData,
+}: {
+ account: Account;
+ programAccount: ProgramAccountInfo;
+ programData: ProgramDataAccountInfo;
+}) {
+ const refresh = useFetchAccountInfo();
+ return (
+
+
+
+ Program Account
+
+
+
+
+
+
+ Address |
+
+
+ |
+
+
+ Balance (SOL) |
+
+ {lamportsToSolString(account.lamports || 0)}
+ |
+
+
+ Executable |
+ Yes |
+
+
+ Executable Data |
+
+
+ |
+
+
+ Upgradeable |
+
+ {programData.authority !== null ? "Yes" : "No"}
+ |
+
+
+ Last Deployed Slot |
+
+
+ |
+
+ {programData.authority !== null && (
+
+ Upgrade Authority |
+
+
+ |
+
+ )}
+
+
+ );
+}
diff --git a/explorer/src/pages/AccountDetailsPage.tsx b/explorer/src/pages/AccountDetailsPage.tsx
index b9b0ae77ce..d21dc312d9 100644
--- a/explorer/src/pages/AccountDetailsPage.tsx
+++ b/explorer/src/pages/AccountDetailsPage.tsx
@@ -29,6 +29,7 @@ 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";
const TABS_LOOKUP: { [id: string]: Tab } = {
"spl-token:mint": {
@@ -174,7 +175,15 @@ function DetailsSections({ pubkey, tab }: { pubkey: PublicKey; tab?: string }) {
function InfoSection({ account }: { account: Account }) {
const data = account?.details?.data;
- if (data && data.program === "stake") {
+ if (data && data.program === "bpf-upgradeable-loader") {
+ return (
+
+ );
+ } else if (data && data.program === "stake") {
return (
;
+export const ProgramAccountInfo = pick({
+ programData: Pubkey,
+});
+
+export type ProgramAccount = StructType;
+export const ProgramAccount = pick({
+ type: literal("program"),
+ info: ProgramAccountInfo,
+});
+
+export type ProgramDataAccountInfo = StructType;
+export const ProgramDataAccountInfo = pick({
+ authority: nullable(Pubkey),
+ // don't care about data yet
+ slot: number(),
+});
+
+export type ProgramDataAccount = StructType;
+export const ProgramDataAccount = pick({
+ type: literal("programData"),
+ info: ProgramDataAccountInfo,
+});