diff --git a/explorer/src/components/TransactionModal.tsx b/explorer/src/components/TransactionModal.tsx
index 1d4b77000a..45fcfa7756 100644
--- a/explorer/src/components/TransactionModal.tsx
+++ b/explorer/src/components/TransactionModal.tsx
@@ -5,8 +5,13 @@ import {
ActionType,
Selected
} from "../providers/transactions";
+import { displayAddress } from "../utils";
import { useBlocks } from "../providers/blocks";
-import { LAMPORTS_PER_SOL } from "@solana/web3.js";
+import {
+ LAMPORTS_PER_SOL,
+ TransferParams,
+ CreateAccountParams
+} from "@solana/web3.js";
function TransactionModal() {
const { selected } = useTransactions();
@@ -45,24 +50,34 @@ function TransactionModal() {
function TransactionDetails({ selected }: { selected: Selected }) {
const { blocks } = useBlocks();
const block = blocks[selected.slot];
- if (!block)
- return {"Transaction block not found"};
+
+ const renderError = (content: React.ReactNode) => {
+ return (
+
+ {content}
+
+ );
+ };
+
+ if (!block) return renderError("Transaction block not found");
if (!block.transactions) {
- return (
-
+ return renderError(
+ <>
Loading
-
+ >
);
}
const details = block.transactions[selected.signature];
- if (!details)
- return {"Transaction not found"};
+ if (!details) return renderError("Transaction not found");
- if (details.transfers.length === 0)
- return {"No transfers"};
+ const { transfers, creates } = details;
+ if (transfers.length === 0 && creates.length === 0)
+ return renderError(
+ "Details for this transaction's instructions are not yet supported"
+ );
let i = 0;
return (
@@ -71,42 +86,15 @@ function TransactionDetails({ selected }: { selected: Selected }) {
return (
{i > 1 ?
: null}
-
-
-
-
-
-
From
-
-
- {transfer.fromPubkey.toBase58()}
-
-
-
-
-
-
-
-
To
-
-
- {transfer.toPubkey.toBase58()}
-
-
-
-
-
-
-
-
Amount (SOL)
-
-
- {`◎${(1.0 * transfer.lamports) / LAMPORTS_PER_SOL}`}
-
-
-
-
-
+
+
+ );
+ })}
+ {details.creates.map(create => {
+ return (
+
+ {i > 1 ?
: null}
+
);
})}
@@ -114,4 +102,63 @@ function TransactionDetails({ selected }: { selected: Selected }) {
);
}
+function TransferDetails({ transfer }: { transfer: TransferParams }) {
+ return (
+
+
+
+ {transfer.fromPubkey.toBase58()}
+
+
+ {transfer.toPubkey.toBase58()}
+
+
+ {`◎${(1.0 * transfer.lamports) / LAMPORTS_PER_SOL}`}
+
+
+
+ );
+}
+
+function CreateDetails({ create }: { create: CreateAccountParams }) {
+ return (
+
+
+
+ {create.fromPubkey.toBase58()}
+
+
+ {create.newAccountPubkey.toBase58()}
+
+
+ {`◎${(1.0 * create.lamports) / LAMPORTS_PER_SOL}`}
+
+ {create.space}
+
+ {displayAddress(create.programId)}
+
+
+
+ );
+}
+
+function ListGroupItem({
+ label,
+ children
+}: {
+ label: string;
+ children: React.ReactNode;
+}) {
+ return (
+
+
+
+
{label}
+
+
{children}
+
+
+ );
+}
+
export default TransactionModal;
diff --git a/explorer/src/providers/blocks.tsx b/explorer/src/providers/blocks.tsx
index 711b3d08cd..6b2ca70efa 100644
--- a/explorer/src/providers/blocks.tsx
+++ b/explorer/src/providers/blocks.tsx
@@ -5,7 +5,8 @@ import {
Transaction,
TransferParams,
SystemProgram,
- SystemInstruction
+ SystemInstruction,
+ CreateAccountParams
} from "@solana/web3.js";
import { useCluster, ClusterStatus } from "./cluster";
import { useTransactions } from "./transactions";
@@ -19,6 +20,7 @@ export enum Status {
export interface TransactionDetails {
transaction: Transaction;
transfers: Array;
+ creates: Array;
}
type Transactions = { [signature: string]: TransactionDetails };
@@ -152,6 +154,38 @@ export function BlocksProvider({ children }: BlocksProviderProps) {
);
}
+function decodeTransfers(tx: Transaction) {
+ const transferInstructions = tx.instructions
+ .filter(ix => ix.programId.equals(SystemProgram.programId))
+ .filter(ix => SystemInstruction.decodeInstructionType(ix) === "Transfer");
+
+ let transfers: TransferParams[] = [];
+ transferInstructions.forEach(ix => {
+ try {
+ transfers.push(SystemInstruction.decodeTransfer(ix));
+ } catch (err) {
+ console.error(ix, err);
+ }
+ });
+ return transfers;
+}
+
+function decodeCreates(tx: Transaction) {
+ const createInstructions = tx.instructions
+ .filter(ix => ix.programId.equals(SystemProgram.programId))
+ .filter(ix => SystemInstruction.decodeInstructionType(ix) === "Create");
+
+ let creates: CreateAccountParams[] = [];
+ createInstructions.forEach(ix => {
+ try {
+ creates.push(SystemInstruction.decodeCreateAccount(ix));
+ } catch (err) {
+ console.error(ix, err);
+ }
+ });
+ return creates;
+}
+
async function fetchBlock(dispatch: Dispatch, slot: number, url: string) {
dispatch({
type: ActionType.Update,
@@ -166,25 +200,11 @@ async function fetchBlock(dispatch: Dispatch, slot: number, url: string) {
block.transactions.forEach(({ transaction }) => {
const signature = transaction.signature;
if (signature) {
- const transferInstructions = transaction.instructions
- .filter(ix => ix.programId.equals(SystemProgram.programId))
- .filter(
- ix => SystemInstruction.decodeInstructionType(ix) === "Transfer"
- );
-
- let transfers: TransferParams[] = [];
- transferInstructions.forEach(ix => {
- try {
- transfers.push(SystemInstruction.decodeTransfer(ix));
- } catch (err) {
- console.log(ix, err);
- }
- });
-
const sig = bs58.encode(signature);
transactions[sig] = {
transaction,
- transfers
+ transfers: decodeTransfers(transaction),
+ creates: decodeCreates(transaction)
};
}
});