Explorer: Refactor parsed transaction handling (#27050)
This commit is contained in:
parent
c03f3b1436
commit
9348a23dfa
|
@ -394,8 +394,8 @@ const TokenTransactionRow = React.memo(
|
||||||
statusText = "Success";
|
statusText = "Success";
|
||||||
}
|
}
|
||||||
|
|
||||||
const instructions =
|
const transactionWithMeta = details?.data?.transactionWithMeta;
|
||||||
details?.data?.transaction?.transaction.message.instructions;
|
const instructions = transactionWithMeta?.transaction.message.instructions;
|
||||||
if (!instructions)
|
if (!instructions)
|
||||||
return (
|
return (
|
||||||
<tr key={tx.signature}>
|
<tr key={tx.signature}>
|
||||||
|
@ -424,9 +424,7 @@ const TokenTransactionRow = React.memo(
|
||||||
|
|
||||||
let tokenInstructionNames: InstructionType[] = [];
|
let tokenInstructionNames: InstructionType[] = [];
|
||||||
|
|
||||||
if (details?.data?.transaction) {
|
if (transactionWithMeta) {
|
||||||
const transaction = details.data.transaction;
|
|
||||||
|
|
||||||
tokenInstructionNames = instructions
|
tokenInstructionNames = instructions
|
||||||
.map((ix, index): InstructionType | undefined => {
|
.map((ix, index): InstructionType | undefined => {
|
||||||
let name = "Unknown";
|
let name = "Unknown";
|
||||||
|
@ -437,11 +435,11 @@ const TokenTransactionRow = React.memo(
|
||||||
)[] = [];
|
)[] = [];
|
||||||
|
|
||||||
if (
|
if (
|
||||||
transaction.meta?.innerInstructions &&
|
transactionWithMeta.meta?.innerInstructions &&
|
||||||
(cluster !== Cluster.MainnetBeta ||
|
(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) {
|
if (ix.index === index) {
|
||||||
ix.instructions.forEach((inner) => {
|
ix.instructions.forEach((inner) => {
|
||||||
innerInstructions.push(inner);
|
innerInstructions.push(inner);
|
||||||
|
@ -451,9 +449,9 @@ const TokenTransactionRow = React.memo(
|
||||||
}
|
}
|
||||||
|
|
||||||
let transactionInstruction;
|
let transactionInstruction;
|
||||||
if (transaction?.transaction) {
|
if (transactionWithMeta?.transaction) {
|
||||||
transactionInstruction = intoTransactionInstruction(
|
transactionInstruction = intoTransactionInstruction(
|
||||||
transaction.transaction,
|
transactionWithMeta.transaction,
|
||||||
ix
|
ix
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
ParsedConfirmedTransaction,
|
ParsedTransactionWithMeta,
|
||||||
ParsedInstruction,
|
ParsedInstruction,
|
||||||
PartiallyDecodedInstruction,
|
PartiallyDecodedInstruction,
|
||||||
PublicKey,
|
PublicKey,
|
||||||
|
@ -47,23 +47,23 @@ export function TokenInstructionsCard({ pubkey }: { pubkey: PublicKey }) {
|
||||||
const { hasTimestamps, detailsList } = React.useMemo(() => {
|
const { hasTimestamps, detailsList } = React.useMemo(() => {
|
||||||
const detailedHistoryMap =
|
const detailedHistoryMap =
|
||||||
history?.data?.transactionMap ||
|
history?.data?.transactionMap ||
|
||||||
new Map<string, ParsedConfirmedTransaction>();
|
new Map<string, ParsedTransactionWithMeta>();
|
||||||
const hasTimestamps = transactionRows.some((element) => element.blockTime);
|
const hasTimestamps = transactionRows.some((element) => element.blockTime);
|
||||||
const detailsList: React.ReactNode[] = [];
|
const detailsList: React.ReactNode[] = [];
|
||||||
const mintMap = new Map<string, MintDetails>();
|
const mintMap = new Map<string, MintDetails>();
|
||||||
|
|
||||||
transactionRows.forEach(
|
transactionRows.forEach(
|
||||||
({ signatureInfo, signature, blockTime, statusClass, statusText }) => {
|
({ signatureInfo, signature, blockTime, statusClass, statusText }) => {
|
||||||
const parsed = detailedHistoryMap.get(signature);
|
const transactionWithMeta = detailedHistoryMap.get(signature);
|
||||||
if (!parsed) return;
|
if (!transactionWithMeta) return;
|
||||||
|
|
||||||
extractMintDetails(parsed, mintMap);
|
extractMintDetails(transactionWithMeta, mintMap);
|
||||||
|
|
||||||
let instructions: (ParsedInstruction | PartiallyDecodedInstruction)[] =
|
let instructions: (ParsedInstruction | PartiallyDecodedInstruction)[] =
|
||||||
[];
|
[];
|
||||||
|
|
||||||
InstructionContainer.create(parsed).instructions.forEach(
|
InstructionContainer.create(transactionWithMeta).instructions.forEach(
|
||||||
({ instruction, inner }, index) => {
|
({ instruction, inner }) => {
|
||||||
if (isRelevantInstruction(pubkey, address, mintMap, instruction)) {
|
if (isRelevantInstruction(pubkey, address, mintMap, instruction)) {
|
||||||
instructions.push(instruction);
|
instructions.push(instruction);
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ export function TokenInstructionsCard({ pubkey }: { pubkey: PublicKey }) {
|
||||||
const programId = ix.programId;
|
const programId = ix.programId;
|
||||||
|
|
||||||
const instructionName = getTokenInstructionName(
|
const instructionName = getTokenInstructionName(
|
||||||
parsed,
|
transactionWithMeta,
|
||||||
ix,
|
ix,
|
||||||
signatureInfo
|
signatureInfo
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
ParsedConfirmedTransaction,
|
ParsedTransactionWithMeta,
|
||||||
ParsedInstruction,
|
ParsedInstruction,
|
||||||
PartiallyDecodedInstruction,
|
PartiallyDecodedInstruction,
|
||||||
PublicKey,
|
PublicKey,
|
||||||
|
@ -68,23 +68,23 @@ export function TokenTransfersCard({ pubkey }: { pubkey: PublicKey }) {
|
||||||
const { hasTimestamps, detailsList } = React.useMemo(() => {
|
const { hasTimestamps, detailsList } = React.useMemo(() => {
|
||||||
const detailedHistoryMap =
|
const detailedHistoryMap =
|
||||||
history?.data?.transactionMap ||
|
history?.data?.transactionMap ||
|
||||||
new Map<string, ParsedConfirmedTransaction>();
|
new Map<string, ParsedTransactionWithMeta>();
|
||||||
const hasTimestamps = transactionRows.some((element) => element.blockTime);
|
const hasTimestamps = transactionRows.some((element) => element.blockTime);
|
||||||
const detailsList: React.ReactNode[] = [];
|
const detailsList: React.ReactNode[] = [];
|
||||||
const mintMap = new Map<string, MintDetails>();
|
const mintMap = new Map<string, MintDetails>();
|
||||||
|
|
||||||
transactionRows.forEach(
|
transactionRows.forEach(
|
||||||
({ signature, blockTime, statusText, statusClass }) => {
|
({ signature, blockTime, statusText, statusClass }) => {
|
||||||
const parsed = detailedHistoryMap.get(signature);
|
const transactionWithMeta = detailedHistoryMap.get(signature);
|
||||||
if (!parsed) return;
|
if (!transactionWithMeta) return;
|
||||||
|
|
||||||
// Extract mint information from token deltas
|
// Extract mint information from token deltas
|
||||||
// (used to filter out non-checked tokens transfers not belonging to this mint)
|
// (used to filter out non-checked tokens transfers not belonging to this mint)
|
||||||
extractMintDetails(parsed, mintMap);
|
extractMintDetails(transactionWithMeta, mintMap);
|
||||||
|
|
||||||
// Extract all transfers from transaction
|
// Extract all transfers from transaction
|
||||||
let transfers: IndexedTransfer[] = [];
|
let transfers: IndexedTransfer[] = [];
|
||||||
InstructionContainer.create(parsed).instructions.forEach(
|
InstructionContainer.create(transactionWithMeta).instructions.forEach(
|
||||||
({ instruction, inner }, index) => {
|
({ instruction, inner }, index) => {
|
||||||
const transfer = getTransfer(instruction, cluster, signature);
|
const transfer = getTransfer(instruction, cluster, signature);
|
||||||
if (transfer) {
|
if (transfer) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ParsedConfirmedTransaction } from "@solana/web3.js";
|
import { ParsedTransactionWithMeta } from "@solana/web3.js";
|
||||||
|
|
||||||
export type MintDetails = {
|
export type MintDetails = {
|
||||||
decimals: number;
|
decimals: number;
|
||||||
|
@ -6,13 +6,15 @@ export type MintDetails = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export function extractMintDetails(
|
export function extractMintDetails(
|
||||||
parsedTransaction: ParsedConfirmedTransaction,
|
transactionWithMeta: ParsedTransactionWithMeta,
|
||||||
mintMap: Map<string, MintDetails>
|
mintMap: Map<string, MintDetails>
|
||||||
) {
|
) {
|
||||||
if (parsedTransaction.meta?.preTokenBalances) {
|
if (transactionWithMeta.meta?.preTokenBalances) {
|
||||||
parsedTransaction.meta.preTokenBalances.forEach((balance) => {
|
transactionWithMeta.meta.preTokenBalances.forEach((balance) => {
|
||||||
const account =
|
const account =
|
||||||
parsedTransaction.transaction.message.accountKeys[balance.accountIndex];
|
transactionWithMeta.transaction.message.accountKeys[
|
||||||
|
balance.accountIndex
|
||||||
|
];
|
||||||
mintMap.set(account.pubkey.toBase58(), {
|
mintMap.set(account.pubkey.toBase58(), {
|
||||||
decimals: balance.uiTokenAmount.decimals,
|
decimals: balance.uiTokenAmount.decimals,
|
||||||
mint: balance.mint,
|
mint: balance.mint,
|
||||||
|
@ -20,10 +22,12 @@ export function extractMintDetails(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parsedTransaction.meta?.postTokenBalances) {
|
if (transactionWithMeta.meta?.postTokenBalances) {
|
||||||
parsedTransaction.meta.postTokenBalances.forEach((balance) => {
|
transactionWithMeta.meta.postTokenBalances.forEach((balance) => {
|
||||||
const account =
|
const account =
|
||||||
parsedTransaction.transaction.message.accountKeys[balance.accountIndex];
|
transactionWithMeta.transaction.message.accountKeys[
|
||||||
|
balance.accountIndex
|
||||||
|
];
|
||||||
mintMap.set(account.pubkey.toBase58(), {
|
mintMap.set(account.pubkey.toBase58(), {
|
||||||
decimals: balance.uiTokenAmount.decimals,
|
decimals: balance.uiTokenAmount.decimals,
|
||||||
mint: balance.mint,
|
mint: balance.mint,
|
||||||
|
|
|
@ -66,11 +66,11 @@ export function InstructionsSection({ signature }: SignatureProps) {
|
||||||
const refreshDetails = () => fetchDetails(signature);
|
const refreshDetails = () => fetchDetails(signature);
|
||||||
|
|
||||||
const result = status?.data?.info?.result;
|
const result = status?.data?.info?.result;
|
||||||
if (!result || !details?.data?.transaction) {
|
const transactionWithMeta = details?.data?.transactionWithMeta;
|
||||||
|
if (!result || !transactionWithMeta) {
|
||||||
return <ErrorCard retry={refreshDetails} text="No instructions found" />;
|
return <ErrorCard retry={refreshDetails} text="No instructions found" />;
|
||||||
}
|
}
|
||||||
const { meta } = details.data.transaction;
|
const { meta, transaction } = transactionWithMeta;
|
||||||
const { transaction } = details.data?.transaction;
|
|
||||||
|
|
||||||
if (transaction.message.instructions.length === 0) {
|
if (transaction.message.instructions.length === 0) {
|
||||||
return <ErrorCard retry={refreshDetails} text="No instructions found" />;
|
return <ErrorCard retry={refreshDetails} text="No instructions found" />;
|
||||||
|
@ -83,7 +83,7 @@ export function InstructionsSection({ signature }: SignatureProps) {
|
||||||
if (
|
if (
|
||||||
meta?.innerInstructions &&
|
meta?.innerInstructions &&
|
||||||
(cluster !== Cluster.MainnetBeta ||
|
(cluster !== Cluster.MainnetBeta ||
|
||||||
details.data.transaction.slot >= INNER_INSTRUCTIONS_START_SLOT)
|
transactionWithMeta.slot >= INNER_INSTRUCTIONS_START_SLOT)
|
||||||
) {
|
) {
|
||||||
meta.innerInstructions.forEach((parsed: ParsedInnerInstruction) => {
|
meta.innerInstructions.forEach((parsed: ParsedInnerInstruction) => {
|
||||||
if (!innerInstructions[parsed.index]) {
|
if (!innerInstructions[parsed.index]) {
|
||||||
|
|
|
@ -9,12 +9,12 @@ export function ProgramLogSection({ signature }: SignatureProps) {
|
||||||
const { cluster, url } = useCluster();
|
const { cluster, url } = useCluster();
|
||||||
const details = useTransactionDetails(signature);
|
const details = useTransactionDetails(signature);
|
||||||
|
|
||||||
const transaction = details?.data?.transaction;
|
const transactionWithMeta = details?.data?.transactionWithMeta;
|
||||||
if (!transaction) return null;
|
if (!transactionWithMeta) return null;
|
||||||
const message = transaction.transaction.message;
|
const message = transactionWithMeta.transaction.message;
|
||||||
|
|
||||||
const logMessages = transaction.meta?.logMessages || null;
|
const logMessages = transactionWithMeta.meta?.logMessages || null;
|
||||||
const err = transaction.meta?.err || null;
|
const err = transactionWithMeta.meta?.err || null;
|
||||||
|
|
||||||
let prettyLogs = null;
|
let prettyLogs = null;
|
||||||
if (logMessages !== null) {
|
if (logMessages !== null) {
|
||||||
|
|
|
@ -28,11 +28,10 @@ export function TokenBalancesCard({ signature }: SignatureProps) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const preTokenBalances = details.data?.transaction?.meta?.preTokenBalances;
|
const transactionWithMeta = details.data?.transactionWithMeta;
|
||||||
const postTokenBalances = details.data?.transaction?.meta?.postTokenBalances;
|
const preTokenBalances = transactionWithMeta?.meta?.preTokenBalances;
|
||||||
|
const postTokenBalances = transactionWithMeta?.meta?.postTokenBalances;
|
||||||
const accountKeys =
|
const accountKeys = transactionWithMeta?.transaction.message.accountKeys;
|
||||||
details.data?.transaction?.transaction.message.accountKeys;
|
|
||||||
|
|
||||||
if (!preTokenBalances || !postTokenBalances || !accountKeys) {
|
if (!preTokenBalances || !postTokenBalances || !accountKeys) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -193,8 +193,9 @@ function StatusCard({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fee = details?.data?.transaction?.meta?.fee;
|
const transactionWithMeta = details?.data?.transactionWithMeta;
|
||||||
const transaction = details?.data?.transaction?.transaction;
|
const fee = transactionWithMeta?.meta?.fee;
|
||||||
|
const transaction = transactionWithMeta?.transaction;
|
||||||
const blockhash = transaction?.message.recentBlockhash;
|
const blockhash = transaction?.message.recentBlockhash;
|
||||||
const isNonce = (() => {
|
const isNonce = (() => {
|
||||||
if (!transaction || transaction.message.instructions.length < 1) {
|
if (!transaction || transaction.message.instructions.length < 1) {
|
||||||
|
@ -338,7 +339,8 @@ function DetailsSection({ signature }: SignatureProps) {
|
||||||
const details = useTransactionDetails(signature);
|
const details = useTransactionDetails(signature);
|
||||||
const fetchDetails = useFetchTransactionDetails();
|
const fetchDetails = useFetchTransactionDetails();
|
||||||
const status = useTransactionStatus(signature);
|
const status = useTransactionStatus(signature);
|
||||||
const transaction = details?.data?.transaction?.transaction;
|
const transactionWithMeta = details?.data?.transactionWithMeta;
|
||||||
|
const transaction = transactionWithMeta?.transaction;
|
||||||
const message = transaction?.message;
|
const message = transaction?.message;
|
||||||
const { status: clusterStatus } = useCluster();
|
const { status: clusterStatus } = useCluster();
|
||||||
const refreshDetails = () => fetchDetails(signature);
|
const refreshDetails = () => fetchDetails(signature);
|
||||||
|
@ -360,7 +362,7 @@ function DetailsSection({ signature }: SignatureProps) {
|
||||||
return <LoadingCard />;
|
return <LoadingCard />;
|
||||||
} else if (details.status === FetchStatus.FetchFailed) {
|
} else if (details.status === FetchStatus.FetchFailed) {
|
||||||
return <ErrorCard retry={refreshDetails} text="Failed to fetch details" />;
|
return <ErrorCard retry={refreshDetails} text="Failed to fetch details" />;
|
||||||
} else if (!details.data?.transaction || !message) {
|
} else if (!transactionWithMeta || !message) {
|
||||||
return <ErrorCard text="Details are not available" />;
|
return <ErrorCard text="Details are not available" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,11 +379,12 @@ function DetailsSection({ signature }: SignatureProps) {
|
||||||
function AccountsCard({ signature }: SignatureProps) {
|
function AccountsCard({ signature }: SignatureProps) {
|
||||||
const details = useTransactionDetails(signature);
|
const details = useTransactionDetails(signature);
|
||||||
|
|
||||||
if (!details?.data?.transaction) {
|
const transactionWithMeta = details?.data?.transactionWithMeta;
|
||||||
|
if (!transactionWithMeta) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { meta, transaction } = details.data.transaction;
|
const { meta, transaction } = transactionWithMeta;
|
||||||
const { message } = transaction;
|
const { message } = transaction;
|
||||||
|
|
||||||
if (!meta) {
|
if (!meta) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {
|
||||||
ConfirmedSignatureInfo,
|
ConfirmedSignatureInfo,
|
||||||
TransactionSignature,
|
TransactionSignature,
|
||||||
Connection,
|
Connection,
|
||||||
ParsedConfirmedTransaction,
|
ParsedTransactionWithMeta,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { useCluster, Cluster } from "../cluster";
|
import { useCluster, Cluster } from "../cluster";
|
||||||
import * as Cache from "providers/cache";
|
import * as Cache from "providers/cache";
|
||||||
|
@ -13,7 +13,7 @@ import { reportError } from "utils/sentry";
|
||||||
|
|
||||||
const MAX_TRANSACTION_BATCH_SIZE = 10;
|
const MAX_TRANSACTION_BATCH_SIZE = 10;
|
||||||
|
|
||||||
type TransactionMap = Map<string, ParsedConfirmedTransaction>;
|
type TransactionMap = Map<string, ParsedTransactionWithMeta>;
|
||||||
|
|
||||||
type AccountHistory = {
|
type AccountHistory = {
|
||||||
fetched: ConfirmedSignatureInfo[];
|
fetched: ConfirmedSignatureInfo[];
|
||||||
|
@ -109,11 +109,14 @@ async function fetchParsedTransactions(
|
||||||
0,
|
0,
|
||||||
MAX_TRANSACTION_BATCH_SIZE
|
MAX_TRANSACTION_BATCH_SIZE
|
||||||
);
|
);
|
||||||
const fetched = await connection.getParsedConfirmedTransactions(signatures);
|
const fetched = await connection.getParsedTransactions(signatures);
|
||||||
fetched.forEach(
|
fetched.forEach(
|
||||||
(parsed: ParsedConfirmedTransaction | null, index: number) => {
|
(
|
||||||
if (parsed !== null) {
|
transactionWithMeta: ParsedTransactionWithMeta | null,
|
||||||
transactionMap.set(signatures[index], parsed);
|
index: number
|
||||||
|
) => {
|
||||||
|
if (transactionWithMeta !== null) {
|
||||||
|
transactionMap.set(signatures[index], transactionWithMeta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from "react";
|
||||||
import {
|
import {
|
||||||
Connection,
|
Connection,
|
||||||
TransactionSignature,
|
TransactionSignature,
|
||||||
ParsedConfirmedTransaction,
|
ParsedTransactionWithMeta,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { useCluster, Cluster } from "../cluster";
|
import { useCluster, Cluster } from "../cluster";
|
||||||
import * as Cache from "providers/cache";
|
import * as Cache from "providers/cache";
|
||||||
|
@ -10,7 +10,7 @@ import { ActionType, FetchStatus } from "providers/cache";
|
||||||
import { reportError } from "utils/sentry";
|
import { reportError } from "utils/sentry";
|
||||||
|
|
||||||
export interface Details {
|
export interface Details {
|
||||||
transaction?: ParsedConfirmedTransaction | null;
|
transactionWithMeta?: ParsedTransactionWithMeta | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
type State = Cache.State<Details>;
|
type State = Cache.State<Details>;
|
||||||
|
@ -53,9 +53,9 @@ async function fetchDetails(
|
||||||
});
|
});
|
||||||
|
|
||||||
let fetchStatus;
|
let fetchStatus;
|
||||||
let transaction;
|
let transactionWithMeta;
|
||||||
try {
|
try {
|
||||||
transaction = await new Connection(url).getParsedConfirmedTransaction(
|
transactionWithMeta = await new Connection(url).getParsedTransaction(
|
||||||
signature,
|
signature,
|
||||||
"confirmed"
|
"confirmed"
|
||||||
);
|
);
|
||||||
|
@ -70,7 +70,7 @@ async function fetchDetails(
|
||||||
type: ActionType.Update,
|
type: ActionType.Update,
|
||||||
status: fetchStatus,
|
status: fetchStatus,
|
||||||
key: signature,
|
key: signature,
|
||||||
data: { transaction },
|
data: { transactionWithMeta },
|
||||||
url,
|
url,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { ParsedInfo } from "validators";
|
||||||
import { reportError } from "utils/sentry";
|
import { reportError } from "utils/sentry";
|
||||||
import {
|
import {
|
||||||
ConfirmedSignatureInfo,
|
ConfirmedSignatureInfo,
|
||||||
ParsedConfirmedTransaction,
|
ParsedTransactionWithMeta,
|
||||||
ParsedInstruction,
|
ParsedInstruction,
|
||||||
PartiallyDecodedInstruction,
|
PartiallyDecodedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
|
@ -43,30 +43,31 @@ export interface InstructionItem {
|
||||||
export class InstructionContainer {
|
export class InstructionContainer {
|
||||||
readonly instructions: InstructionItem[];
|
readonly instructions: InstructionItem[];
|
||||||
|
|
||||||
static create(parsedTransaction: ParsedConfirmedTransaction) {
|
static create(transactionWithMeta: ParsedTransactionWithMeta) {
|
||||||
return new InstructionContainer(parsedTransaction);
|
return new InstructionContainer(transactionWithMeta);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(parsedTransaction: ParsedConfirmedTransaction) {
|
constructor(transactionWithMeta: ParsedTransactionWithMeta) {
|
||||||
this.instructions = parsedTransaction.transaction.message.instructions.map(
|
this.instructions =
|
||||||
(instruction) => {
|
transactionWithMeta.transaction.message.instructions.map(
|
||||||
if ("parsed" in instruction) {
|
(instruction) => {
|
||||||
if (typeof instruction.parsed === "object") {
|
if ("parsed" in instruction) {
|
||||||
instruction.parsed = create(instruction.parsed, ParsedInfo);
|
if (typeof instruction.parsed === "object") {
|
||||||
} else if (typeof instruction.parsed !== "string") {
|
instruction.parsed = create(instruction.parsed, ParsedInfo);
|
||||||
throw new Error("Unexpected parsed response");
|
} else if (typeof instruction.parsed !== "string") {
|
||||||
|
throw new Error("Unexpected parsed response");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
instruction,
|
||||||
|
inner: [],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
if (transactionWithMeta.meta?.innerInstructions) {
|
||||||
instruction,
|
for (let inner of transactionWithMeta.meta.innerInstructions) {
|
||||||
inner: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (parsedTransaction.meta?.innerInstructions) {
|
|
||||||
for (let inner of parsedTransaction.meta.innerInstructions) {
|
|
||||||
this.instructions[inner.index].inner.push(...inner.instructions);
|
this.instructions[inner.index].inner.push(...inner.instructions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,16 +90,16 @@ export function getTokenProgramInstructionName(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTokenInstructionName(
|
export function getTokenInstructionName(
|
||||||
transaction: ParsedConfirmedTransaction,
|
transactionWithMeta: ParsedTransactionWithMeta,
|
||||||
ix: ParsedInstruction | PartiallyDecodedInstruction,
|
ix: ParsedInstruction | PartiallyDecodedInstruction,
|
||||||
signatureInfo: ConfirmedSignatureInfo
|
signatureInfo: ConfirmedSignatureInfo
|
||||||
) {
|
) {
|
||||||
let name = "Unknown";
|
let name = "Unknown";
|
||||||
|
|
||||||
let transactionInstruction;
|
let transactionInstruction;
|
||||||
if (transaction?.transaction) {
|
if (transactionWithMeta?.transaction) {
|
||||||
transactionInstruction = intoTransactionInstruction(
|
transactionInstruction = intoTransactionInstruction(
|
||||||
transaction.transaction,
|
transactionWithMeta.transaction,
|
||||||
ix
|
ix
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -163,7 +164,7 @@ export function getTokenInstructionName(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTokenInstructionType(
|
export function getTokenInstructionType(
|
||||||
transaction: ParsedConfirmedTransaction,
|
transactionWithMeta: ParsedTransactionWithMeta,
|
||||||
ix: ParsedInstruction | PartiallyDecodedInstruction,
|
ix: ParsedInstruction | PartiallyDecodedInstruction,
|
||||||
signatureInfo: ConfirmedSignatureInfo,
|
signatureInfo: ConfirmedSignatureInfo,
|
||||||
index: number
|
index: number
|
||||||
|
@ -171,8 +172,8 @@ export function getTokenInstructionType(
|
||||||
const innerInstructions: (ParsedInstruction | PartiallyDecodedInstruction)[] =
|
const innerInstructions: (ParsedInstruction | PartiallyDecodedInstruction)[] =
|
||||||
[];
|
[];
|
||||||
|
|
||||||
if (transaction.meta?.innerInstructions) {
|
if (transactionWithMeta.meta?.innerInstructions) {
|
||||||
transaction.meta.innerInstructions.forEach((ix) => {
|
transactionWithMeta.meta.innerInstructions.forEach((ix) => {
|
||||||
if (ix.index === index) {
|
if (ix.index === index) {
|
||||||
ix.instructions.forEach((inner) => {
|
ix.instructions.forEach((inner) => {
|
||||||
innerInstructions.push(inner);
|
innerInstructions.push(inner);
|
||||||
|
@ -182,7 +183,8 @@ export function getTokenInstructionType(
|
||||||
}
|
}
|
||||||
|
|
||||||
let name =
|
let name =
|
||||||
getTokenInstructionName(transaction, ix, signatureInfo) || "Unknown";
|
getTokenInstructionName(transactionWithMeta, ix, signatureInfo) ||
|
||||||
|
"Unknown";
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
|
|
Loading…
Reference in New Issue