diff --git a/explorer/src/components/block/BlockAccountsCard.tsx b/explorer/src/components/block/BlockAccountsCard.tsx index 4e98aeeed2..9a78e54e88 100644 --- a/explorer/src/components/block/BlockAccountsCard.tsx +++ b/explorer/src/components/block/BlockAccountsCard.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { ConfirmedBlock, PublicKey } from "@solana/web3.js"; +import { BlockResponse, PublicKey } from "@solana/web3.js"; import { Address } from "components/common/Address"; type AccountStats = { @@ -9,18 +9,19 @@ type AccountStats = { const PAGE_SIZE = 25; -export function BlockAccountsCard({ block }: { block: ConfirmedBlock }) { +export function BlockAccountsCard({ block }: { block: BlockResponse }) { const [numDisplayed, setNumDisplayed] = React.useState(10); const totalTransactions = block.transactions.length; const accountStats = React.useMemo(() => { const statsMap = new Map(); block.transactions.forEach((tx) => { + const message = tx.transaction.message; const txSet = new Map(); - tx.transaction.instructions.forEach((ix) => { - ix.keys.forEach((key) => { - const address = key.pubkey.toBase58(); - txSet.set(address, key.isWritable); + message.instructions.forEach((ix) => { + ix.accounts.forEach((index) => { + const address = message.accountKeys[index].toBase58(); + txSet.set(address, message.isAccountWritable(index)); }); }); diff --git a/explorer/src/components/block/BlockHistoryCard.tsx b/explorer/src/components/block/BlockHistoryCard.tsx index 5878ee8855..f92438dc70 100644 --- a/explorer/src/components/block/BlockHistoryCard.tsx +++ b/explorer/src/components/block/BlockHistoryCard.tsx @@ -1,12 +1,11 @@ import React from "react"; -import { ConfirmedBlock } from "@solana/web3.js"; +import { BlockResponse } from "@solana/web3.js"; import { ErrorCard } from "components/common/ErrorCard"; import { Signature } from "components/common/Signature"; -import bs58 from "bs58"; const PAGE_SIZE = 25; -export function BlockHistoryCard({ block }: { block: ConfirmedBlock }) { +export function BlockHistoryCard({ block }: { block: BlockResponse }) { const [numDisplayed, setNumDisplayed] = React.useState(PAGE_SIZE); if (block.transactions.length === 0) { @@ -32,7 +31,7 @@ export function BlockHistoryCard({ block }: { block: ConfirmedBlock }) { let statusText; let statusClass; let signature: React.ReactNode; - if (tx.meta?.err || !tx.transaction.signature) { + if (tx.meta?.err || tx.transaction.signatures.length === 0) { statusClass = "warning"; statusText = "Failed"; } else { @@ -40,12 +39,9 @@ export function BlockHistoryCard({ block }: { block: ConfirmedBlock }) { statusText = "Success"; } - if (tx.transaction.signature) { + if (tx.transaction.signatures.length > 0) { signature = ( - + ); } diff --git a/explorer/src/components/block/BlockOverviewCard.tsx b/explorer/src/components/block/BlockOverviewCard.tsx index 473cc147f5..2168667436 100644 --- a/explorer/src/components/block/BlockOverviewCard.tsx +++ b/explorer/src/components/block/BlockOverviewCard.tsx @@ -7,7 +7,7 @@ import { Slot } from "components/common/Slot"; import { ClusterStatus, useCluster } from "providers/cluster"; import { BlockHistoryCard } from "./BlockHistoryCard"; import { BlockRewardsCard } from "./BlockRewardsCard"; -import { ConfirmedBlock } from "@solana/web3.js"; +import { BlockResponse } from "@solana/web3.js"; import { NavLink } from "react-router-dom"; import { clusterPath } from "utils/url"; import { BlockProgramsCard } from "./BlockProgramsCard"; @@ -134,7 +134,7 @@ function MoreSection({ tab, }: { slot: number; - block: ConfirmedBlock; + block: BlockResponse; tab?: string; }) { return ( diff --git a/explorer/src/components/block/BlockProgramsCard.tsx b/explorer/src/components/block/BlockProgramsCard.tsx index 71b92898f6..bd1fc7123d 100644 --- a/explorer/src/components/block/BlockProgramsCard.tsx +++ b/explorer/src/components/block/BlockProgramsCard.tsx @@ -1,9 +1,9 @@ import React from "react"; -import { ConfirmedBlock, PublicKey } from "@solana/web3.js"; +import { BlockResponse, PublicKey } from "@solana/web3.js"; import { Address } from "components/common/Address"; import { TableCardBody } from "components/common/TableCardBody"; -export function BlockProgramsCard({ block }: { block: ConfirmedBlock }) { +export function BlockProgramsCard({ block }: { block: BlockResponse }) { const totalTransactions = block.transactions.length; const txSuccesses = new Map(); const txFrequency = new Map(); @@ -11,25 +11,24 @@ export function BlockProgramsCard({ block }: { block: ConfirmedBlock }) { let totalInstructions = 0; block.transactions.forEach((tx) => { - totalInstructions += tx.transaction.instructions.length; + const message = tx.transaction.message; + totalInstructions += message.instructions.length; const programUsed = new Set(); - const trackProgramId = (programId: PublicKey) => { + const trackProgram = (index: number) => { + if (index >= message.accountKeys.length) return; + const programId = message.accountKeys[index]; const programAddress = programId.toBase58(); programUsed.add(programAddress); const frequency = ixFrequency.get(programAddress); ixFrequency.set(programAddress, frequency ? frequency + 1 : 1); }; - tx.transaction.instructions.forEach((ix, index) => { - trackProgramId(ix.programId); - tx.meta?.innerInstructions?.forEach((inner) => { - if (inner.index !== index) return; - totalInstructions += inner.instructions.length; - inner.instructions.forEach((innerIx) => { - if (innerIx.programIdIndex >= ix.keys.length) return; - trackProgramId(ix.keys[innerIx.programIdIndex].pubkey); - }); - }); + message.instructions.forEach((ix) => trackProgram(ix.programIdIndex)); + tx.meta?.innerInstructions?.forEach((inner) => { + totalInstructions += inner.instructions.length; + inner.instructions.forEach((innerIx) => + trackProgram(innerIx.programIdIndex) + ); }); const successful = tx.meta?.err === null; diff --git a/explorer/src/components/block/BlockRewardsCard.tsx b/explorer/src/components/block/BlockRewardsCard.tsx index 62993a48cd..4d740703b2 100644 --- a/explorer/src/components/block/BlockRewardsCard.tsx +++ b/explorer/src/components/block/BlockRewardsCard.tsx @@ -1,11 +1,11 @@ import React from "react"; import { lamportsToSolString } from "utils"; -import { ConfirmedBlock, PublicKey } from "@solana/web3.js"; +import { BlockResponse, PublicKey } from "@solana/web3.js"; import { Address } from "components/common/Address"; const PAGE_SIZE = 10; -export function BlockRewardsCard({ block }: { block: ConfirmedBlock }) { +export function BlockRewardsCard({ block }: { block: BlockResponse }) { const [rewardsDisplayed, setRewardsDisplayed] = React.useState(PAGE_SIZE); if (!block.rewards || block.rewards.length < 1) { diff --git a/explorer/src/components/instruction/InstructionCard.tsx b/explorer/src/components/instruction/InstructionCard.tsx index 048734652d..f42da9a8e1 100644 --- a/explorer/src/components/instruction/InstructionCard.tsx +++ b/explorer/src/components/instruction/InstructionCard.tsx @@ -38,10 +38,12 @@ export function InstructionCard({ const [showRaw, setShowRaw] = React.useState(defaultRaw || false); const signature = useContext(SignatureContext); const details = useTransactionDetails(signature); + let raw: TransactionInstruction | undefined = undefined; if (details && childIndex === undefined) { - raw = details?.data?.raw?.transaction.instructions[index]; + raw = details?.data?.raw?.instructions[index]; } + const fetchRaw = useFetchRawTransaction(); const fetchRawTrigger = () => fetchRaw(signature); diff --git a/explorer/src/components/transaction/InstructionsSection.tsx b/explorer/src/components/transaction/InstructionsSection.tsx index dc38223fec..fe16a5cc05 100644 --- a/explorer/src/components/transaction/InstructionsSection.tsx +++ b/explorer/src/components/transaction/InstructionsSection.tsx @@ -7,7 +7,6 @@ import { PartiallyDecodedInstruction, PublicKey, SignatureResult, - Transaction, TransactionSignature, } from "@solana/web3.js"; import { BpfLoaderDetailsCard } from "components/instruction/bpf-loader/BpfLoaderDetailsCard"; @@ -59,8 +58,6 @@ export function InstructionsSection({ signature }: SignatureProps) { if (!status?.data?.info || !details?.data?.transaction) return null; - const raw = details.data.raw?.transaction; - const { transaction } = details.data.transaction; const { meta } = details.data.transaction; @@ -106,7 +103,6 @@ export function InstructionsSection({ signature }: SignatureProps) { signature, tx: transaction, childIndex, - raw, }); innerCards.push(res); @@ -120,7 +116,6 @@ export function InstructionsSection({ signature }: SignatureProps) { signature, tx: transaction, innerCards, - raw, }); } ); @@ -147,7 +142,6 @@ function renderInstructionCard({ signature, innerCards, childIndex, - raw, }: { ix: ParsedInstruction | PartiallyDecodedInstruction; tx: ParsedTransaction; @@ -156,7 +150,6 @@ function renderInstructionCard({ signature: TransactionSignature; innerCards?: JSX.Element[]; childIndex?: number; - raw?: Transaction; }) { const key = `${index}-${childIndex}`; diff --git a/explorer/src/providers/block.tsx b/explorer/src/providers/block.tsx index e25dd455de..facf9102f5 100644 --- a/explorer/src/providers/block.tsx +++ b/explorer/src/providers/block.tsx @@ -1,7 +1,7 @@ import React from "react"; import * as Sentry from "@sentry/react"; import * as Cache from "providers/cache"; -import { Connection, ConfirmedBlock } from "@solana/web3.js"; +import { Connection, BlockResponse } from "@solana/web3.js"; import { useCluster, Cluster } from "./cluster"; export enum FetchStatus { @@ -16,7 +16,7 @@ export enum ActionType { } type Block = { - block?: ConfirmedBlock; + block?: BlockResponse; }; type State = Cache.State; @@ -72,18 +72,18 @@ export async function fetchBlock( try { const connection = new Connection(url, "finalized"); - data = { block: await connection.getConfirmedBlock(Number(key)) }; - status = FetchStatus.Fetched; - } catch (err) { - const error = err as Error; - if (error.message.includes("not found")) { - data = {} as Block; + const block = await connection.getBlock(Number(key)); + if (block === null) { + data = {}; status = FetchStatus.Fetched; } else { - status = FetchStatus.FetchFailed; - if (cluster !== Cluster.Custom) { - Sentry.captureException(error, { tags: { url } }); - } + data = { block }; + status = FetchStatus.Fetched; + } + } catch (err) { + status = FetchStatus.FetchFailed; + if (cluster !== Cluster.Custom) { + Sentry.captureException(err, { tags: { url } }); } } diff --git a/explorer/src/providers/transactions/details.tsx b/explorer/src/providers/transactions/details.tsx index 93352feef6..35227c2bc2 100644 --- a/explorer/src/providers/transactions/details.tsx +++ b/explorer/src/providers/transactions/details.tsx @@ -3,7 +3,7 @@ import { Connection, TransactionSignature, ParsedConfirmedTransaction, - ConfirmedTransaction, + Transaction, } from "@solana/web3.js"; import { useCluster, Cluster } from "../cluster"; import * as Cache from "providers/cache"; @@ -12,7 +12,7 @@ import { reportError } from "utils/sentry"; export interface Details { transaction?: ParsedConfirmedTransaction | null; - raw?: ConfirmedTransaction | null; + raw?: Transaction | null; } type State = Cache.State
; @@ -128,17 +128,23 @@ async function fetchRawTransaction( url: string ) { let fetchStatus; - let transaction; try { - transaction = await new Connection(url).getConfirmedTransaction(signature); + const response = await new Connection(url).getTransaction(signature); fetchStatus = FetchStatus.Fetched; + + let data: Details = { raw: null }; + if (response !== null) { + const { message, signatures } = response.transaction; + data = { + raw: Transaction.populate(message, signatures), + }; + } + dispatch({ type: ActionType.Update, status: fetchStatus, key: signature, - data: { - raw: transaction, - }, + data, url, }); } catch (error) {