2021-03-13 09:11:59 -08:00
import React from "react" ;
import { TableCardBody } from "components/common/TableCardBody" ;
2021-06-21 16:53:06 -07:00
import { SolBalance } from "utils" ;
2021-03-13 09:11:59 -08:00
import { Account , useFetchAccountInfo } from "providers/accounts" ;
import { Address } from "components/common/Address" ;
import {
ProgramAccountInfo ,
ProgramBufferAccountInfo ,
ProgramDataAccountInfo ,
UpgradeableLoaderAccount ,
} from "validators/accounts/upgradeable-program" ;
import { Slot } from "components/common/Slot" ;
import { addressLabel } from "utils/tx" ;
import { useCluster } from "providers/cluster" ;
import { ErrorCard } from "components/common/ErrorCard" ;
2021-08-17 12:07:10 -07:00
import { UnknownAccountCard } from "components/account/UnknownAccountCard" ;
2022-01-16 04:46:02 -08:00
import { Downloadable } from "components/common/Downloadable" ;
2022-02-06 02:11:12 -08:00
import { CheckingBadge , VerifiedBadge } from "components/common/VerifiedBadge" ;
import { InfoTooltip } from "components/common/InfoTooltip" ;
import { useVerifiableBuilds } from "utils/program-verification" ;
2022-03-31 02:23:32 -07:00
import { SecurityTXTBadge } from "components/common/SecurityTXTBadge" ;
2021-03-13 09:11:59 -08:00
export function UpgradeableLoaderAccountSection ( {
account ,
parsedData ,
programData ,
} : {
account : Account ;
parsedData : UpgradeableLoaderAccount ;
programData : ProgramDataAccountInfo | undefined ;
} ) {
switch ( parsedData . type ) {
case "program" : {
if ( programData === undefined ) {
return < ErrorCard text = "Invalid Upgradeable Program account" / > ;
}
return (
< UpgradeableProgramSection
account = { account }
programAccount = { parsedData . info }
programData = { programData }
/ >
) ;
}
case "programData" : {
return (
< UpgradeableProgramDataSection
account = { account }
programData = { parsedData . info }
/ >
) ;
}
case "buffer" : {
return (
< UpgradeableProgramBufferSection
account = { account }
programBuffer = { parsedData . info }
/ >
) ;
}
2021-08-17 12:07:10 -07:00
case "uninitialized" : {
return < UnknownAccountCard account = { account } / > ;
}
2021-03-13 09:11:59 -08:00
}
}
export function UpgradeableProgramSection ( {
account ,
programAccount ,
programData ,
} : {
account : Account ;
programAccount : ProgramAccountInfo ;
programData : ProgramDataAccountInfo ;
} ) {
const refresh = useFetchAccountInfo ( ) ;
const { cluster } = useCluster ( ) ;
const label = addressLabel ( account . pubkey . toBase58 ( ) , cluster ) ;
2022-02-06 02:11:12 -08:00
const { loading , verifiableBuilds } = useVerifiableBuilds ( account . pubkey ) ;
2021-03-13 09:11:59 -08:00
return (
< div className = "card" >
< div className = "card-header" >
< h3 className = "card-header-title mb-0 d-flex align-items-center" >
Program Account
< / h3 >
< button
className = "btn btn-white btn-sm"
onClick = { ( ) = > refresh ( account . pubkey ) }
>
2021-11-28 12:49:22 -08:00
< span className = "fe fe-refresh-cw me-2" > < / span >
2021-03-13 09:11:59 -08:00
Refresh
< / button >
< / div >
< TableCardBody >
< tr >
< td > Address < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end" >
2021-03-13 09:11:59 -08:00
< Address pubkey = { account . pubkey } alignRight raw / >
< / td >
< / tr >
{ label && (
< tr >
< td > Address Label < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end" > { label } < / td >
2021-03-13 09:11:59 -08:00
< / tr >
) }
< tr >
< td > Balance ( SOL ) < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end text-uppercase" >
2021-06-21 16:53:06 -07:00
< SolBalance lamports = { account . lamports || 0 } / >
2021-03-13 09:11:59 -08:00
< / td >
< / tr >
< tr >
< td > Executable < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end" > Yes < / td >
2021-03-13 09:11:59 -08:00
< / tr >
< tr >
< td > Executable Data < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end" >
2021-03-13 09:11:59 -08:00
< Address pubkey = { programAccount . programData } alignRight link / >
< / td >
< / tr >
< tr >
< td > Upgradeable < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end" >
2021-03-13 09:11:59 -08:00
{ programData . authority !== null ? "Yes" : "No" }
< / td >
< / tr >
2022-02-06 02:11:12 -08:00
< tr >
< td >
< LastVerifiedBuildLabel / >
< / td >
< td className = "text-lg-end" >
{ loading ? (
< CheckingBadge / >
) : (
< >
2022-02-09 02:40:56 -08:00
{ verifiableBuilds . map ( ( b , i ) = > (
< VerifiedBadge
key = { i }
verifiableBuild = { b }
deploySlot = { programData . slot }
/ >
2022-02-06 02:11:12 -08:00
) ) }
< / >
) }
< / td >
< / tr >
2022-03-31 02:23:32 -07:00
< tr >
< td >
< SecurityLabel / >
< / td >
< td className = "text-lg-end" >
< SecurityTXTBadge
programData = { programData }
pubkey = { account . pubkey }
/ >
< / td >
< / tr >
2021-03-13 09:11:59 -08:00
< tr >
< td > Last Deployed Slot < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end" >
2021-03-13 09:11:59 -08:00
< Slot slot = { programData . slot } link / >
< / td >
< / tr >
{ programData . authority !== null && (
< tr >
< td > Upgrade Authority < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end" >
2021-03-13 09:11:59 -08:00
< Address pubkey = { programData . authority } alignRight link / >
< / td >
< / tr >
) }
< / TableCardBody >
< / div >
) ;
}
2022-03-31 02:23:32 -07:00
function SecurityLabel() {
return (
< InfoTooltip text = "Security.txt helps security researchers to contact developers if they find security bugs." >
< a
rel = "noopener noreferrer"
target = "_blank"
href = "https://github.com/neodyme-labs/solana-security-txt"
>
< span className = "security-txt-link-color-hack-reee" > Security . txt < / span >
< span className = "fe fe-external-link ms-2" > < / span >
< / a >
< / InfoTooltip >
) ;
}
2022-02-06 02:11:12 -08:00
function LastVerifiedBuildLabel() {
return (
< InfoTooltip text = "Indicates whether the program currently deployed on-chain is verified to match the associated published source code, when it is available." >
Verifiable Build Status
< / InfoTooltip >
) ;
}
2021-03-13 09:11:59 -08:00
export function UpgradeableProgramDataSection ( {
account ,
programData ,
} : {
account : Account ;
programData : ProgramDataAccountInfo ;
} ) {
const refresh = useFetchAccountInfo ( ) ;
return (
< div className = "card" >
< div className = "card-header" >
< h3 className = "card-header-title mb-0 d-flex align-items-center" >
Program Executable Data Account
< / h3 >
< button
className = "btn btn-white btn-sm"
onClick = { ( ) = > refresh ( account . pubkey ) }
>
2021-11-28 12:49:22 -08:00
< span className = "fe fe-refresh-cw me-2" > < / span >
2021-03-13 09:11:59 -08:00
Refresh
< / button >
< / div >
< TableCardBody >
< tr >
< td > Address < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end" >
2021-03-13 09:11:59 -08:00
< Address pubkey = { account . pubkey } alignRight raw / >
< / td >
< / tr >
< tr >
< td > Balance ( SOL ) < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end text-uppercase" >
2021-06-21 16:53:06 -07:00
< SolBalance lamports = { account . lamports || 0 } / >
2021-03-13 09:11:59 -08:00
< / td >
< / tr >
{ account . details ? . space !== undefined && (
< tr >
< td > Data ( Bytes ) < / td >
2022-01-16 04:46:02 -08:00
< td className = "text-lg-end" >
< Downloadable
data = { programData . data [ 0 ] }
filename = { ` ${ account . pubkey . toString ( ) } .bin ` }
>
< span className = "me-2" > { account . details . space } < / span >
< / Downloadable >
< / td >
2021-03-13 09:11:59 -08:00
< / tr >
) }
< tr >
< td > Upgradeable < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end" >
2021-03-13 09:11:59 -08:00
{ programData . authority !== null ? "Yes" : "No" }
< / td >
< / tr >
< tr >
< td > Last Deployed Slot < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end" >
2021-03-13 09:11:59 -08:00
< Slot slot = { programData . slot } link / >
< / td >
< / tr >
{ programData . authority !== null && (
< tr >
< td > Upgrade Authority < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end" >
2021-03-13 09:11:59 -08:00
< Address pubkey = { programData . authority } alignRight link / >
< / td >
< / tr >
) }
< / TableCardBody >
< / div >
) ;
}
export function UpgradeableProgramBufferSection ( {
account ,
programBuffer ,
} : {
account : Account ;
programBuffer : ProgramBufferAccountInfo ;
} ) {
const refresh = useFetchAccountInfo ( ) ;
return (
< div className = "card" >
< div className = "card-header" >
< h3 className = "card-header-title mb-0 d-flex align-items-center" >
Program Deploy Buffer Account
< / h3 >
< button
className = "btn btn-white btn-sm"
onClick = { ( ) = > refresh ( account . pubkey ) }
>
2021-11-28 12:49:22 -08:00
< span className = "fe fe-refresh-cw me-2" > < / span >
2021-03-13 09:11:59 -08:00
Refresh
< / button >
< / div >
< TableCardBody >
< tr >
< td > Address < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end" >
2021-03-13 09:11:59 -08:00
< Address pubkey = { account . pubkey } alignRight raw / >
< / td >
< / tr >
< tr >
< td > Balance ( SOL ) < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end text-uppercase" >
2021-06-21 16:53:06 -07:00
< SolBalance lamports = { account . lamports || 0 } / >
2021-03-13 09:11:59 -08:00
< / td >
< / tr >
{ account . details ? . space !== undefined && (
< tr >
< td > Data ( Bytes ) < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end" > { account . details . space } < / td >
2021-03-13 09:11:59 -08:00
< / tr >
) }
{ programBuffer . authority !== null && (
< tr >
< td > Deploy Authority < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end" >
2021-03-13 09:11:59 -08:00
< Address pubkey = { programBuffer . authority } alignRight link / >
< / td >
< / tr >
) }
{ account . details && (
< tr >
< td > Owner < / td >
2021-11-28 12:49:22 -08:00
< td className = "text-lg-end" >
2021-03-13 09:11:59 -08:00
< Address pubkey = { account . details . owner } alignRight link / >
< / td >
< / tr >
) }
< / TableCardBody >
< / div >
) ;
}