diff --git a/explorer/src/components/TransactionDetails.tsx b/explorer/src/components/TransactionDetails.tsx
index 2dd55ec9bb..5087672da0 100644
--- a/explorer/src/components/TransactionDetails.tsx
+++ b/explorer/src/components/TransactionDetails.tsx
@@ -1,5 +1,4 @@
import React from "react";
-import bs58 from "bs58";
import {
Source,
useFetchTransactionStatus,
@@ -10,19 +9,15 @@ import {
} from "../providers/transactions";
import { fetchDetails } from "providers/transactions/details";
import { useCluster, useClusterModal } from "providers/cluster";
-import {
- TransactionSignature,
- TransactionInstruction,
- TransferParams,
- CreateAccountParams,
- SystemProgram,
- SignatureResult
-} from "@solana/web3.js";
+import { TransactionSignature, SystemInstruction } from "@solana/web3.js";
import ClusterStatusButton from "components/ClusterStatusButton";
import { lamportsToSolString } from "utils";
-import { displayAddress, decodeCreate, decodeTransfer } from "utils/tx";
+import { displayAddress } from "utils/tx";
import Copyable from "./Copyable";
import { useHistory, useLocation } from "react-router-dom";
+import { TransferDetailsCard } from "./instruction/TransferDetailsCard";
+import { CreateDetailsCard } from "./instruction/CreateDetailsCard";
+import { RawDetailsCard } from "./instruction/RawDetailsCard";
type Props = { signature: TransactionSignature };
export default function TransactionDetails({ signature }: Props) {
@@ -265,50 +260,6 @@ function AccountsCard({ signature }: Props) {
);
}
-function ixResult(result: SignatureResult, index: number) {
- if (result.err) {
- const err = result.err as any;
- const ixError = err["InstructionError"];
- if (ixError && Array.isArray(ixError)) {
- const [errorIndex, error] = ixError;
- if (Number.isInteger(errorIndex) && errorIndex === index) {
- return ["warning", `Error: ${JSON.stringify(error)}`];
- }
- }
- return ["dark"];
- }
- return ["success"];
-}
-
-type InstructionProps = {
- title: string;
- children: React.ReactNode;
- result: SignatureResult;
- index: number;
-};
-
-function InstructionCard({ title, children, result, index }: InstructionProps) {
- const [resultClass, errorString] = ixResult(result, index);
- return (
-
-
-
-
- #{index + 1}
-
- {title}
-
-
-
- {errorString}
-
-
-
-
{children}
-
- );
-}
-
function InstructionsSection({ signature }: Props) {
const status = useTransactionStatus(signature);
const details = useTransactionDetails(signature);
@@ -325,39 +276,24 @@ function InstructionsSection({ signature }: Props) {
const result = status.info.result;
const instructionDetails = transaction.instructions.map((ix, index) => {
- const transfer = decodeTransfer(ix);
- if (transfer) {
- return (
-
-
-
- );
+ const props = { ix, result, index };
+
+ let instructionType;
+ try {
+ instructionType = SystemInstruction.decodeInstructionType(ix);
+ } catch (err) {
+ console.error(err);
+ return ;
}
- const create = decodeCreate(ix);
- if (create) {
- return (
-
-
-
- );
+ switch (instructionType) {
+ case "Transfer":
+ return ;
+ case "Create":
+ return ;
+ default:
+ return ;
}
-
- return (
-
-
-
- );
});
return (
@@ -374,190 +310,6 @@ function InstructionsSection({ signature }: Props) {
);
}
-function TransferDetails({
- ix,
- transfer
-}: {
- ix: TransactionInstruction;
- transfer: TransferParams;
-}) {
- const from = transfer.fromPubkey.toBase58();
- const to = transfer.toPubkey.toBase58();
- const [fromMeta, toMeta] = ix.keys;
- return (
- <>
-
- Program |
-
-
- {displayAddress(SystemProgram.programId)}
-
- |
-
-
-
-
- From Address
- {!fromMeta.isWritable && (
- Readonly
- )}
- {fromMeta.isSigner && (
- Signer
- )}
- |
-
-
- {from}
-
- |
-
-
-
-
- To Address
- {!toMeta.isWritable && (
- Readonly
- )}
- {toMeta.isSigner && (
- Signer
- )}
- |
-
-
- {to}
-
- |
-
-
-
- Transfer Amount (SOL) |
- {lamportsToSolString(transfer.lamports)} |
-
- >
- );
-}
-
-function CreateDetails({
- ix,
- create
-}: {
- ix: TransactionInstruction;
- create: CreateAccountParams;
-}) {
- const from = create.fromPubkey.toBase58();
- const newKey = create.newAccountPubkey.toBase58();
- const [fromMeta, newMeta] = ix.keys;
-
- return (
- <>
-
- Program |
-
-
- {displayAddress(SystemProgram.programId)}
-
- |
-
-
-
-
- From Address
- {!fromMeta.isWritable && (
- Readonly
- )}
- {fromMeta.isSigner && (
- Signer
- )}
- |
-
-
- {from}
-
- |
-
-
-
-
- New Address
- {!newMeta.isWritable && (
- Readonly
- )}
- {newMeta.isSigner && (
- Signer
- )}
- |
-
-
- {newKey}
-
- |
-
-
-
- Transfer Amount (SOL) |
- {lamportsToSolString(create.lamports)} |
-
-
-
- Allocated Space (Bytes) |
- {create.space} |
-
-
-
- Assigned Owner |
-
-
- {displayAddress(create.programId)}
-
- |
-
- >
- );
-}
-
-function RawDetails({ ix }: { ix: TransactionInstruction }) {
- return (
- <>
-
- Program |
-
-
- {displayAddress(ix.programId)}
-
- |
-
-
- {ix.keys.map(({ pubkey, isSigner, isWritable }, keyIndex) => (
-
-
- Account #{keyIndex + 1}
- {!isWritable && (
- Readonly
- )}
- {isSigner && (
- Signer
- )}
- |
-
-
- {pubkey.toBase58()}
-
- |
-
- ))}
-
-
- Raw Data (Base58) |
-
-
- {bs58.encode(ix.data)}
-
- |
-
- >
- );
-}
-
function LoadingCard() {
return (
diff --git a/explorer/src/components/instruction/CreateDetailsCard.tsx b/explorer/src/components/instruction/CreateDetailsCard.tsx
new file mode 100644
index 0000000000..21dc57c7f3
--- /dev/null
+++ b/explorer/src/components/instruction/CreateDetailsCard.tsx
@@ -0,0 +1,98 @@
+import React from "react";
+import {
+ TransactionInstruction,
+ SystemProgram,
+ SignatureResult,
+ SystemInstruction
+} from "@solana/web3.js";
+import { lamportsToSolString } from "utils";
+import { displayAddress } from "utils/tx";
+import { InstructionCard } from "./InstructionCard";
+import Copyable from "components/Copyable";
+import { RawDetailsCard } from "./RawDetailsCard";
+
+export function CreateDetailsCard(props: {
+ ix: TransactionInstruction;
+ index: number;
+ result: SignatureResult;
+}) {
+ const { ix, index, result } = props;
+
+ let create;
+ try {
+ create = SystemInstruction.decodeCreateAccount(ix);
+ } catch (err) {
+ console.error(err);
+ return
;
+ }
+
+ const from = create.fromPubkey.toBase58();
+ const newKey = create.newAccountPubkey.toBase58();
+ const [fromMeta, newMeta] = ix.keys;
+
+ return (
+
+
+ Program |
+
+
+ {displayAddress(SystemProgram.programId)}
+
+ |
+
+
+
+
+ From Address
+ {!fromMeta.isWritable && (
+ Readonly
+ )}
+ {fromMeta.isSigner && (
+ Signer
+ )}
+ |
+
+
+ {from}
+
+ |
+
+
+
+
+ New Address
+ {!newMeta.isWritable && (
+ Readonly
+ )}
+ {newMeta.isSigner && (
+ Signer
+ )}
+ |
+
+
+ {newKey}
+
+ |
+
+
+
+ Transfer Amount (SOL) |
+ {lamportsToSolString(create.lamports)} |
+
+
+
+ Allocated Space (Bytes) |
+ {create.space} |
+
+
+
+ Assigned Owner |
+
+
+ {displayAddress(create.programId)}
+
+ |
+
+
+ );
+}
diff --git a/explorer/src/components/instruction/InstructionCard.tsx b/explorer/src/components/instruction/InstructionCard.tsx
new file mode 100644
index 0000000000..3db9ef6e15
--- /dev/null
+++ b/explorer/src/components/instruction/InstructionCard.tsx
@@ -0,0 +1,55 @@
+import React from "react";
+import { SignatureResult } from "@solana/web3.js";
+
+type InstructionProps = {
+ title: string;
+ children: React.ReactNode;
+ result: SignatureResult;
+ index: number;
+};
+
+export function InstructionCard({
+ title,
+ children,
+ result,
+ index
+}: InstructionProps) {
+ const [resultClass, errorString] = ixResult(result, index);
+ return (
+
+
+
+
+ #{index + 1}
+
+ {title}
+
+
+
+ {errorString}
+
+
+
+
+
+ );
+}
+
+function ixResult(result: SignatureResult, index: number) {
+ if (result.err) {
+ const err = result.err as any;
+ const ixError = err["InstructionError"];
+ if (ixError && Array.isArray(ixError)) {
+ const [errorIndex, error] = ixError;
+ if (Number.isInteger(errorIndex) && errorIndex === index) {
+ return ["warning", `Error: ${JSON.stringify(error)}`];
+ }
+ }
+ return ["dark"];
+ }
+ return ["success"];
+}
diff --git a/explorer/src/components/instruction/RawDetailsCard.tsx b/explorer/src/components/instruction/RawDetailsCard.tsx
new file mode 100644
index 0000000000..f5c13de623
--- /dev/null
+++ b/explorer/src/components/instruction/RawDetailsCard.tsx
@@ -0,0 +1,57 @@
+import React from "react";
+import bs58 from "bs58";
+import { TransactionInstruction, SignatureResult } from "@solana/web3.js";
+import { displayAddress } from "utils/tx";
+import { InstructionCard } from "./InstructionCard";
+import Copyable from "components/Copyable";
+
+export function RawDetailsCard({
+ ix,
+ index,
+ result
+}: {
+ ix: TransactionInstruction;
+ index: number;
+ result: SignatureResult;
+}) {
+ return (
+
+
+ Program |
+
+
+ {displayAddress(ix.programId)}
+
+ |
+
+
+ {ix.keys.map(({ pubkey, isSigner, isWritable }, keyIndex) => (
+
+
+ Account #{keyIndex + 1}
+ {!isWritable && (
+ Readonly
+ )}
+ {isSigner && (
+ Signer
+ )}
+ |
+
+
+ {pubkey.toBase58()}
+
+ |
+
+ ))}
+
+
+ Raw Data (Base58) |
+
+
+ {bs58.encode(ix.data)}
+
+ |
+
+
+ );
+}
diff --git a/explorer/src/components/instruction/TransferDetailsCard.tsx b/explorer/src/components/instruction/TransferDetailsCard.tsx
new file mode 100644
index 0000000000..160e06d098
--- /dev/null
+++ b/explorer/src/components/instruction/TransferDetailsCard.tsx
@@ -0,0 +1,83 @@
+import React from "react";
+import {
+ TransactionInstruction,
+ SystemProgram,
+ SignatureResult,
+ SystemInstruction
+} from "@solana/web3.js";
+import { lamportsToSolString } from "utils";
+import { displayAddress } from "utils/tx";
+import { InstructionCard } from "./InstructionCard";
+import Copyable from "components/Copyable";
+import { RawDetailsCard } from "./RawDetailsCard";
+
+export function TransferDetailsCard(props: {
+ ix: TransactionInstruction;
+ index: number;
+ result: SignatureResult;
+}) {
+ const { ix, index, result } = props;
+
+ let transfer;
+ try {
+ transfer = SystemInstruction.decodeTransfer(ix);
+ } catch (err) {
+ console.error(err);
+ return
;
+ }
+
+ const from = transfer.fromPubkey.toBase58();
+ const to = transfer.toPubkey.toBase58();
+ const [fromMeta, toMeta] = ix.keys;
+ return (
+
+
+ Program |
+
+
+ {displayAddress(SystemProgram.programId)}
+
+ |
+
+
+
+
+ From Address
+ {!fromMeta.isWritable && (
+ Readonly
+ )}
+ {fromMeta.isSigner && (
+ Signer
+ )}
+ |
+
+
+ {from}
+
+ |
+
+
+
+
+ To Address
+ {!toMeta.isWritable && (
+ Readonly
+ )}
+ {toMeta.isSigner && (
+ Signer
+ )}
+ |
+
+
+ {to}
+
+ |
+
+
+
+ Transfer Amount (SOL) |
+ {lamportsToSolString(transfer.lamports)} |
+
+
+ );
+}
diff --git a/explorer/src/utils/tx.ts b/explorer/src/utils/tx.ts
index 797a9d588b..7f00dbd688 100644
--- a/explorer/src/utils/tx.ts
+++ b/explorer/src/utils/tx.ts
@@ -4,10 +4,6 @@ import {
StakeProgram,
VOTE_PROGRAM_ID,
BpfLoader,
- TransferParams,
- SystemInstruction,
- CreateAccountParams,
- TransactionInstruction,
SYSVAR_CLOCK_PUBKEY,
SYSVAR_RENT_PUBKEY,
SYSVAR_REWARDS_PUBKEY,
@@ -53,31 +49,3 @@ export function displayAddress(pubkey: PublicKey): string {
address
);
}
-
-export function decodeTransfer(
- ix: TransactionInstruction
-): TransferParams | null {
- if (!ix.programId.equals(SystemProgram.programId)) return null;
-
- try {
- if (SystemInstruction.decodeInstructionType(ix) !== "Transfer") return null;
- return SystemInstruction.decodeTransfer(ix);
- } catch (err) {
- console.error(ix, err);
- return null;
- }
-}
-
-export function decodeCreate(
- ix: TransactionInstruction
-): CreateAccountParams | null {
- if (!ix.programId.equals(SystemProgram.programId)) return null;
-
- try {
- if (SystemInstruction.decodeInstructionType(ix) !== "Create") return null;
- return SystemInstruction.decodeCreateAccount(ix);
- } catch (err) {
- console.error(ix, err);
- return null;
- }
-}