Improve the UI of the transaction modal
This commit is contained in:
parent
bcb10b0536
commit
ed470564e6
|
@ -6,6 +6,7 @@ import {
|
|||
Selected
|
||||
} from "../providers/transactions";
|
||||
import { useBlocks } from "../providers/blocks";
|
||||
import { LAMPORTS_PER_SOL } from "@solana/web3.js";
|
||||
|
||||
function TransactionModal() {
|
||||
const { selected } = useTransactions();
|
||||
|
@ -16,14 +17,16 @@ function TransactionModal() {
|
|||
const renderContent = () => {
|
||||
if (!selected) return null;
|
||||
return (
|
||||
<div className="modal-dialog modal-dialog-center">
|
||||
<div className="modal-content">
|
||||
<div className="modal-body" onClick={e => e.stopPropagation()}>
|
||||
<span className="close" onClick={onClose}>
|
||||
×
|
||||
</span>
|
||||
<div className="modal-dialog modal-dialog-centered">
|
||||
<div className="modal-content" onClick={e => e.stopPropagation()}>
|
||||
<div className="modal-card card">
|
||||
<div className="card-header">
|
||||
<h4 className="card-header-title">Transaction Details</h4>
|
||||
|
||||
<h2 className="text-center mb-4 mt-4">Transaction Details</h2>
|
||||
<button type="button" className="close" onClick={onClose}>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<TransactionDetails selected={selected} />
|
||||
</div>
|
||||
|
@ -33,10 +36,7 @@ function TransactionModal() {
|
|||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`modal fade fixed-right${show ? " show" : ""}`}
|
||||
onClick={onClose}
|
||||
>
|
||||
<div className={`modal fade${show ? " show" : ""}`} onClick={onClose}>
|
||||
{renderContent()}
|
||||
</div>
|
||||
);
|
||||
|
@ -45,16 +45,73 @@ function TransactionModal() {
|
|||
function TransactionDetails({ selected }: { selected: Selected }) {
|
||||
const { blocks } = useBlocks();
|
||||
const block = blocks[selected.slot];
|
||||
if (!block) return <span>{"block not found"}</span>;
|
||||
if (!block)
|
||||
return <span className="text-info">{"Transaction block not found"}</span>;
|
||||
|
||||
if (!block.transactions) {
|
||||
return <span>loading</span>;
|
||||
return (
|
||||
<span className="text-info">
|
||||
<span className="spinner-grow spinner-grow-sm mr-2"></span>
|
||||
Loading
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
const tx = block.transactions[selected.signature];
|
||||
if (!tx) return <span>{"sig not found"}</span>;
|
||||
const details = block.transactions[selected.signature];
|
||||
if (!details)
|
||||
return <span className="text-info">{"Transaction not found"}</span>;
|
||||
|
||||
return <code>{JSON.stringify(tx)}</code>;
|
||||
if (details.transfers.length === 0)
|
||||
return <span className="text-info">{"No transfers"}</span>;
|
||||
|
||||
let i = 0;
|
||||
return (
|
||||
<>
|
||||
{details.transfers.map(transfer => {
|
||||
return (
|
||||
<div key={++i}>
|
||||
{i > 1 ? <hr className="mb-4"></hr> : null}
|
||||
<div className="card-body">
|
||||
<div className="list-group list-group-flush my-n3">
|
||||
<div className="list-group-item">
|
||||
<div className="row align-items-center">
|
||||
<div className="col">
|
||||
<h5 className="mb-0">From</h5>
|
||||
</div>
|
||||
<div className="col-auto">
|
||||
<code>{transfer.fromPubkey.toBase58()}</code>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="list-group-item">
|
||||
<div className="row align-items-center">
|
||||
<div className="col">
|
||||
<h5 className="mb-0">To</h5>
|
||||
</div>
|
||||
<div className="col-auto">
|
||||
<code>{transfer.toPubkey.toBase58()}</code>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="list-group-item">
|
||||
<div className="row align-items-center">
|
||||
<div className="col">
|
||||
<h5 className="mb-0">Amount (SOL)</h5>
|
||||
</div>
|
||||
<div className="col-auto">
|
||||
{`◎${(1.0 * transfer.lamports) / LAMPORTS_PER_SOL}`}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default TransactionModal;
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
import React from "react";
|
||||
import bs58 from "bs58";
|
||||
import { Connection, Transaction } from "@solana/web3.js";
|
||||
import {
|
||||
Connection,
|
||||
Transaction,
|
||||
TransferParams,
|
||||
SystemProgram,
|
||||
SystemInstruction
|
||||
} from "@solana/web3.js";
|
||||
import { useCluster, ClusterStatus } from "./cluster";
|
||||
import { useTransactions } from "./transactions";
|
||||
|
||||
|
@ -10,7 +16,12 @@ export enum Status {
|
|||
Success
|
||||
}
|
||||
|
||||
type Transactions = { [signature: string]: Transaction };
|
||||
export interface TransactionDetails {
|
||||
transaction: Transaction;
|
||||
transfers: Array<TransferParams>;
|
||||
}
|
||||
|
||||
type Transactions = { [signature: string]: TransactionDetails };
|
||||
export interface Block {
|
||||
status: Status;
|
||||
transactions?: Transactions;
|
||||
|
@ -155,8 +166,26 @@ 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;
|
||||
transactions[sig] = {
|
||||
transaction,
|
||||
transfers
|
||||
};
|
||||
}
|
||||
});
|
||||
status = Status.Success;
|
||||
|
|
Loading…
Reference in New Issue