diff --git a/explorer/src/components/account/TokenHistoryCard.tsx b/explorer/src/components/account/TokenHistoryCard.tsx index a2c0f719ce..a2d6e18bba 100644 --- a/explorer/src/components/account/TokenHistoryCard.tsx +++ b/explorer/src/components/account/TokenHistoryCard.tsx @@ -394,8 +394,8 @@ const TokenTransactionRow = React.memo( statusText = "Success"; } - const instructions = - details?.data?.transaction?.transaction.message.instructions; + const transactionWithMeta = details?.data?.transactionWithMeta; + const instructions = transactionWithMeta?.transaction.message.instructions; if (!instructions) return ( @@ -424,9 +424,7 @@ const TokenTransactionRow = React.memo( let tokenInstructionNames: InstructionType[] = []; - if (details?.data?.transaction) { - const transaction = details.data.transaction; - + if (transactionWithMeta) { tokenInstructionNames = instructions .map((ix, index): InstructionType | undefined => { let name = "Unknown"; @@ -437,11 +435,11 @@ const TokenTransactionRow = React.memo( )[] = []; if ( - transaction.meta?.innerInstructions && + transactionWithMeta.meta?.innerInstructions && (cluster !== Cluster.MainnetBeta || - transaction.slot >= INNER_INSTRUCTIONS_START_SLOT) + transactionWithMeta.slot >= INNER_INSTRUCTIONS_START_SLOT) ) { - transaction.meta.innerInstructions.forEach((ix) => { + transactionWithMeta.meta.innerInstructions.forEach((ix) => { if (ix.index === index) { ix.instructions.forEach((inner) => { innerInstructions.push(inner); @@ -451,9 +449,9 @@ const TokenTransactionRow = React.memo( } let transactionInstruction; - if (transaction?.transaction) { + if (transactionWithMeta?.transaction) { transactionInstruction = intoTransactionInstruction( - transaction.transaction, + transactionWithMeta.transaction, ix ); } diff --git a/explorer/src/components/account/history/TokenInstructionsCard.tsx b/explorer/src/components/account/history/TokenInstructionsCard.tsx index e64f04c711..af62281c06 100644 --- a/explorer/src/components/account/history/TokenInstructionsCard.tsx +++ b/explorer/src/components/account/history/TokenInstructionsCard.tsx @@ -1,6 +1,6 @@ import React from "react"; import { - ParsedConfirmedTransaction, + ParsedTransactionWithMeta, ParsedInstruction, PartiallyDecodedInstruction, PublicKey, @@ -47,23 +47,23 @@ export function TokenInstructionsCard({ pubkey }: { pubkey: PublicKey }) { const { hasTimestamps, detailsList } = React.useMemo(() => { const detailedHistoryMap = history?.data?.transactionMap || - new Map(); + new Map(); const hasTimestamps = transactionRows.some((element) => element.blockTime); const detailsList: React.ReactNode[] = []; const mintMap = new Map(); transactionRows.forEach( ({ signatureInfo, signature, blockTime, statusClass, statusText }) => { - const parsed = detailedHistoryMap.get(signature); - if (!parsed) return; + const transactionWithMeta = detailedHistoryMap.get(signature); + if (!transactionWithMeta) return; - extractMintDetails(parsed, mintMap); + extractMintDetails(transactionWithMeta, mintMap); let instructions: (ParsedInstruction | PartiallyDecodedInstruction)[] = []; - InstructionContainer.create(parsed).instructions.forEach( - ({ instruction, inner }, index) => { + InstructionContainer.create(transactionWithMeta).instructions.forEach( + ({ instruction, inner }) => { if (isRelevantInstruction(pubkey, address, mintMap, instruction)) { instructions.push(instruction); } @@ -79,7 +79,7 @@ export function TokenInstructionsCard({ pubkey }: { pubkey: PublicKey }) { const programId = ix.programId; const instructionName = getTokenInstructionName( - parsed, + transactionWithMeta, ix, signatureInfo ); diff --git a/explorer/src/components/account/history/TokenTransfersCard.tsx b/explorer/src/components/account/history/TokenTransfersCard.tsx index 42400ecd50..a2e15de1bd 100644 --- a/explorer/src/components/account/history/TokenTransfersCard.tsx +++ b/explorer/src/components/account/history/TokenTransfersCard.tsx @@ -1,6 +1,6 @@ import React from "react"; import { - ParsedConfirmedTransaction, + ParsedTransactionWithMeta, ParsedInstruction, PartiallyDecodedInstruction, PublicKey, @@ -68,23 +68,23 @@ export function TokenTransfersCard({ pubkey }: { pubkey: PublicKey }) { const { hasTimestamps, detailsList } = React.useMemo(() => { const detailedHistoryMap = history?.data?.transactionMap || - new Map(); + new Map(); const hasTimestamps = transactionRows.some((element) => element.blockTime); const detailsList: React.ReactNode[] = []; const mintMap = new Map(); transactionRows.forEach( ({ signature, blockTime, statusText, statusClass }) => { - const parsed = detailedHistoryMap.get(signature); - if (!parsed) return; + const transactionWithMeta = detailedHistoryMap.get(signature); + if (!transactionWithMeta) return; // Extract mint information from token deltas // (used to filter out non-checked tokens transfers not belonging to this mint) - extractMintDetails(parsed, mintMap); + extractMintDetails(transactionWithMeta, mintMap); // Extract all transfers from transaction let transfers: IndexedTransfer[] = []; - InstructionContainer.create(parsed).instructions.forEach( + InstructionContainer.create(transactionWithMeta).instructions.forEach( ({ instruction, inner }, index) => { const transfer = getTransfer(instruction, cluster, signature); if (transfer) { diff --git a/explorer/src/components/account/history/common.tsx b/explorer/src/components/account/history/common.tsx index cfbd1d0ef7..78e4d55a05 100644 --- a/explorer/src/components/account/history/common.tsx +++ b/explorer/src/components/account/history/common.tsx @@ -1,4 +1,4 @@ -import { ParsedConfirmedTransaction } from "@solana/web3.js"; +import { ParsedTransactionWithMeta } from "@solana/web3.js"; export type MintDetails = { decimals: number; @@ -6,13 +6,15 @@ export type MintDetails = { }; export function extractMintDetails( - parsedTransaction: ParsedConfirmedTransaction, + transactionWithMeta: ParsedTransactionWithMeta, mintMap: Map ) { - if (parsedTransaction.meta?.preTokenBalances) { - parsedTransaction.meta.preTokenBalances.forEach((balance) => { + if (transactionWithMeta.meta?.preTokenBalances) { + transactionWithMeta.meta.preTokenBalances.forEach((balance) => { const account = - parsedTransaction.transaction.message.accountKeys[balance.accountIndex]; + transactionWithMeta.transaction.message.accountKeys[ + balance.accountIndex + ]; mintMap.set(account.pubkey.toBase58(), { decimals: balance.uiTokenAmount.decimals, mint: balance.mint, @@ -20,10 +22,12 @@ export function extractMintDetails( }); } - if (parsedTransaction.meta?.postTokenBalances) { - parsedTransaction.meta.postTokenBalances.forEach((balance) => { + if (transactionWithMeta.meta?.postTokenBalances) { + transactionWithMeta.meta.postTokenBalances.forEach((balance) => { const account = - parsedTransaction.transaction.message.accountKeys[balance.accountIndex]; + transactionWithMeta.transaction.message.accountKeys[ + balance.accountIndex + ]; mintMap.set(account.pubkey.toBase58(), { decimals: balance.uiTokenAmount.decimals, mint: balance.mint, diff --git a/explorer/src/components/transaction/InstructionsSection.tsx b/explorer/src/components/transaction/InstructionsSection.tsx index c47e6dd8bc..d37fbc7fc8 100644 --- a/explorer/src/components/transaction/InstructionsSection.tsx +++ b/explorer/src/components/transaction/InstructionsSection.tsx @@ -66,11 +66,11 @@ export function InstructionsSection({ signature }: SignatureProps) { const refreshDetails = () => fetchDetails(signature); const result = status?.data?.info?.result; - if (!result || !details?.data?.transaction) { + const transactionWithMeta = details?.data?.transactionWithMeta; + if (!result || !transactionWithMeta) { return ; } - const { meta } = details.data.transaction; - const { transaction } = details.data?.transaction; + const { meta, transaction } = transactionWithMeta; if (transaction.message.instructions.length === 0) { return ; @@ -83,7 +83,7 @@ export function InstructionsSection({ signature }: SignatureProps) { if ( meta?.innerInstructions && (cluster !== Cluster.MainnetBeta || - details.data.transaction.slot >= INNER_INSTRUCTIONS_START_SLOT) + transactionWithMeta.slot >= INNER_INSTRUCTIONS_START_SLOT) ) { meta.innerInstructions.forEach((parsed: ParsedInnerInstruction) => { if (!innerInstructions[parsed.index]) { diff --git a/explorer/src/components/transaction/ProgramLogSection.tsx b/explorer/src/components/transaction/ProgramLogSection.tsx index 0f8f44e85f..8142ea279d 100644 --- a/explorer/src/components/transaction/ProgramLogSection.tsx +++ b/explorer/src/components/transaction/ProgramLogSection.tsx @@ -9,12 +9,12 @@ export function ProgramLogSection({ signature }: SignatureProps) { const { cluster, url } = useCluster(); const details = useTransactionDetails(signature); - const transaction = details?.data?.transaction; - if (!transaction) return null; - const message = transaction.transaction.message; + const transactionWithMeta = details?.data?.transactionWithMeta; + if (!transactionWithMeta) return null; + const message = transactionWithMeta.transaction.message; - const logMessages = transaction.meta?.logMessages || null; - const err = transaction.meta?.err || null; + const logMessages = transactionWithMeta.meta?.logMessages || null; + const err = transactionWithMeta.meta?.err || null; let prettyLogs = null; if (logMessages !== null) { diff --git a/explorer/src/components/transaction/TokenBalancesCard.tsx b/explorer/src/components/transaction/TokenBalancesCard.tsx index ff1080b1b9..ef06af5540 100644 --- a/explorer/src/components/transaction/TokenBalancesCard.tsx +++ b/explorer/src/components/transaction/TokenBalancesCard.tsx @@ -28,11 +28,10 @@ export function TokenBalancesCard({ signature }: SignatureProps) { return null; } - const preTokenBalances = details.data?.transaction?.meta?.preTokenBalances; - const postTokenBalances = details.data?.transaction?.meta?.postTokenBalances; - - const accountKeys = - details.data?.transaction?.transaction.message.accountKeys; + const transactionWithMeta = details.data?.transactionWithMeta; + const preTokenBalances = transactionWithMeta?.meta?.preTokenBalances; + const postTokenBalances = transactionWithMeta?.meta?.postTokenBalances; + const accountKeys = transactionWithMeta?.transaction.message.accountKeys; if (!preTokenBalances || !postTokenBalances || !accountKeys) { return null; diff --git a/explorer/src/pages/TransactionDetailsPage.tsx b/explorer/src/pages/TransactionDetailsPage.tsx index e8404d0290..044c46d502 100644 --- a/explorer/src/pages/TransactionDetailsPage.tsx +++ b/explorer/src/pages/TransactionDetailsPage.tsx @@ -193,8 +193,9 @@ function StatusCard({ } } - const fee = details?.data?.transaction?.meta?.fee; - const transaction = details?.data?.transaction?.transaction; + const transactionWithMeta = details?.data?.transactionWithMeta; + const fee = transactionWithMeta?.meta?.fee; + const transaction = transactionWithMeta?.transaction; const blockhash = transaction?.message.recentBlockhash; const isNonce = (() => { if (!transaction || transaction.message.instructions.length < 1) { @@ -338,7 +339,8 @@ function DetailsSection({ signature }: SignatureProps) { const details = useTransactionDetails(signature); const fetchDetails = useFetchTransactionDetails(); const status = useTransactionStatus(signature); - const transaction = details?.data?.transaction?.transaction; + const transactionWithMeta = details?.data?.transactionWithMeta; + const transaction = transactionWithMeta?.transaction; const message = transaction?.message; const { status: clusterStatus } = useCluster(); const refreshDetails = () => fetchDetails(signature); @@ -360,7 +362,7 @@ function DetailsSection({ signature }: SignatureProps) { return ; } else if (details.status === FetchStatus.FetchFailed) { return ; - } else if (!details.data?.transaction || !message) { + } else if (!transactionWithMeta || !message) { return ; } @@ -377,11 +379,12 @@ function DetailsSection({ signature }: SignatureProps) { function AccountsCard({ signature }: SignatureProps) { const details = useTransactionDetails(signature); - if (!details?.data?.transaction) { + const transactionWithMeta = details?.data?.transactionWithMeta; + if (!transactionWithMeta) { return null; } - const { meta, transaction } = details.data.transaction; + const { meta, transaction } = transactionWithMeta; const { message } = transaction; if (!meta) { diff --git a/explorer/src/providers/accounts/history.tsx b/explorer/src/providers/accounts/history.tsx index 4d20df7dd4..618a426a15 100644 --- a/explorer/src/providers/accounts/history.tsx +++ b/explorer/src/providers/accounts/history.tsx @@ -4,7 +4,7 @@ import { ConfirmedSignatureInfo, TransactionSignature, Connection, - ParsedConfirmedTransaction, + ParsedTransactionWithMeta, } from "@solana/web3.js"; import { useCluster, Cluster } from "../cluster"; import * as Cache from "providers/cache"; @@ -13,7 +13,7 @@ import { reportError } from "utils/sentry"; const MAX_TRANSACTION_BATCH_SIZE = 10; -type TransactionMap = Map; +type TransactionMap = Map; type AccountHistory = { fetched: ConfirmedSignatureInfo[]; @@ -109,11 +109,14 @@ async function fetchParsedTransactions( 0, MAX_TRANSACTION_BATCH_SIZE ); - const fetched = await connection.getParsedConfirmedTransactions(signatures); + const fetched = await connection.getParsedTransactions(signatures); fetched.forEach( - (parsed: ParsedConfirmedTransaction | null, index: number) => { - if (parsed !== null) { - transactionMap.set(signatures[index], parsed); + ( + transactionWithMeta: ParsedTransactionWithMeta | null, + index: number + ) => { + if (transactionWithMeta !== null) { + transactionMap.set(signatures[index], transactionWithMeta); } } ); diff --git a/explorer/src/providers/transactions/parsed.tsx b/explorer/src/providers/transactions/parsed.tsx index 73c9d9a133..4ec8b2aaa0 100644 --- a/explorer/src/providers/transactions/parsed.tsx +++ b/explorer/src/providers/transactions/parsed.tsx @@ -2,7 +2,7 @@ import React from "react"; import { Connection, TransactionSignature, - ParsedConfirmedTransaction, + ParsedTransactionWithMeta, } from "@solana/web3.js"; import { useCluster, Cluster } from "../cluster"; import * as Cache from "providers/cache"; @@ -10,7 +10,7 @@ import { ActionType, FetchStatus } from "providers/cache"; import { reportError } from "utils/sentry"; export interface Details { - transaction?: ParsedConfirmedTransaction | null; + transactionWithMeta?: ParsedTransactionWithMeta | null; } type State = Cache.State
; @@ -53,9 +53,9 @@ async function fetchDetails( }); let fetchStatus; - let transaction; + let transactionWithMeta; try { - transaction = await new Connection(url).getParsedConfirmedTransaction( + transactionWithMeta = await new Connection(url).getParsedTransaction( signature, "confirmed" ); @@ -70,7 +70,7 @@ async function fetchDetails( type: ActionType.Update, status: fetchStatus, key: signature, - data: { transaction }, + data: { transactionWithMeta }, url, }); } diff --git a/explorer/src/utils/instruction.ts b/explorer/src/utils/instruction.ts index 7618e1d7bf..429204218c 100644 --- a/explorer/src/utils/instruction.ts +++ b/explorer/src/utils/instruction.ts @@ -7,7 +7,7 @@ import { ParsedInfo } from "validators"; import { reportError } from "utils/sentry"; import { ConfirmedSignatureInfo, - ParsedConfirmedTransaction, + ParsedTransactionWithMeta, ParsedInstruction, PartiallyDecodedInstruction, } from "@solana/web3.js"; @@ -43,30 +43,31 @@ export interface InstructionItem { export class InstructionContainer { readonly instructions: InstructionItem[]; - static create(parsedTransaction: ParsedConfirmedTransaction) { - return new InstructionContainer(parsedTransaction); + static create(transactionWithMeta: ParsedTransactionWithMeta) { + return new InstructionContainer(transactionWithMeta); } - constructor(parsedTransaction: ParsedConfirmedTransaction) { - this.instructions = parsedTransaction.transaction.message.instructions.map( - (instruction) => { - if ("parsed" in instruction) { - if (typeof instruction.parsed === "object") { - instruction.parsed = create(instruction.parsed, ParsedInfo); - } else if (typeof instruction.parsed !== "string") { - throw new Error("Unexpected parsed response"); + constructor(transactionWithMeta: ParsedTransactionWithMeta) { + this.instructions = + transactionWithMeta.transaction.message.instructions.map( + (instruction) => { + if ("parsed" in instruction) { + if (typeof instruction.parsed === "object") { + instruction.parsed = create(instruction.parsed, ParsedInfo); + } else if (typeof instruction.parsed !== "string") { + throw new Error("Unexpected parsed response"); + } } + + return { + instruction, + inner: [], + }; } + ); - return { - instruction, - inner: [], - }; - } - ); - - if (parsedTransaction.meta?.innerInstructions) { - for (let inner of parsedTransaction.meta.innerInstructions) { + if (transactionWithMeta.meta?.innerInstructions) { + for (let inner of transactionWithMeta.meta.innerInstructions) { this.instructions[inner.index].inner.push(...inner.instructions); } } @@ -89,16 +90,16 @@ export function getTokenProgramInstructionName( } export function getTokenInstructionName( - transaction: ParsedConfirmedTransaction, + transactionWithMeta: ParsedTransactionWithMeta, ix: ParsedInstruction | PartiallyDecodedInstruction, signatureInfo: ConfirmedSignatureInfo ) { let name = "Unknown"; let transactionInstruction; - if (transaction?.transaction) { + if (transactionWithMeta?.transaction) { transactionInstruction = intoTransactionInstruction( - transaction.transaction, + transactionWithMeta.transaction, ix ); } @@ -163,7 +164,7 @@ export function getTokenInstructionName( } export function getTokenInstructionType( - transaction: ParsedConfirmedTransaction, + transactionWithMeta: ParsedTransactionWithMeta, ix: ParsedInstruction | PartiallyDecodedInstruction, signatureInfo: ConfirmedSignatureInfo, index: number @@ -171,8 +172,8 @@ export function getTokenInstructionType( const innerInstructions: (ParsedInstruction | PartiallyDecodedInstruction)[] = []; - if (transaction.meta?.innerInstructions) { - transaction.meta.innerInstructions.forEach((ix) => { + if (transactionWithMeta.meta?.innerInstructions) { + transactionWithMeta.meta.innerInstructions.forEach((ix) => { if (ix.index === index) { ix.instructions.forEach((inner) => { innerInstructions.push(inner); @@ -182,7 +183,8 @@ export function getTokenInstructionType( } let name = - getTokenInstructionName(transaction, ix, signatureInfo) || "Unknown"; + getTokenInstructionName(transactionWithMeta, ix, signatureInfo) || + "Unknown"; return { name,