Improve the UI of the transaction modal

This commit is contained in:
Justin Starry 2020-04-05 17:47:57 +08:00 committed by Michael Vines
parent bcb10b0536
commit ed470564e6
2 changed files with 105 additions and 19 deletions

View File

@ -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}>
&times;
</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">&times;</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;

View File

@ -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;