import React, { useMemo, useCallback, useState, useEffect, useContext, } from "react"; import { OverlayTrigger, Tooltip, Card, Row as BRow, Col as BCol, Container, Spinner, } from "react-bootstrap"; import { useParams } from "react-router-dom"; import { Row } from "react-table"; import HashDisp from "src/components/Misc/Disp/HashDisp/HashDisp"; import ToAddrDisp from "src/components/Misc/Disp/ToAddrDisp/ToAddrDisp"; import ViewAllTable from "src/components/ViewAllPages/ViewAllTable/ViewAllTable"; import { NetworkContext, QueryPreservingLink, } from "src/services/network/networkProvider"; import { TransactionDetails } from "src/typings/api"; import { qaToZil, timestampToTimeago, hexAddrToZilAddr, timestampToDisplay, pubKeyToZilAddr, } from "src/utils/Utils"; import { Transaction } from "@zilliqa-js/account/src/transaction"; import { TxBlockObj } from "@zilliqa-js/core/src/types"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCaretSquareLeft, faCaretSquareRight, } from "@fortawesome/free-regular-svg-icons"; import { faCubes, faExclamationCircle, } from "@fortawesome/free-solid-svg-icons"; import LabelStar from "../Misc/LabelComponent/LabelStar"; import NotFoundPage from "../../ErrorPages/NotFoundPage"; import "./TxBlockDetailsPage.css"; const TxBlockDetailsPage: React.FC = () => { const { blockNum } = useParams<{ blockNum: string }>(); const networkContext = useContext(NetworkContext); if (!networkContext) { return (
); } const { dataService, isIsolatedServer } = networkContext; const [error, setError] = useState(null); const [isLoading, setIsLoading] = useState(false); const [isLoadingTrans, setIsLoadingTrans] = useState(false); const [txBlockObj, setTxBlockObj] = useState(null); const [txBlockTxns, setTxBlockTxns] = useState(null); const [latestTxBlockNum, setLatestTxBlockNum] = useState(null); const [transactionData, setTransactionData] = useState< TransactionDetails[] | null >(null); // Fetch data useEffect(() => { setIsLoading(true); if (!dataService || isIsolatedServer === null) return; let latestTxBlockNum: number; let txBlockObj: TxBlockObj; let txBlockTxns: string[]; const getData = async () => { try { if (isNaN(parseInt(blockNum))) throw new Error("Not a valid block number"); if (isIsolatedServer) { txBlockTxns = await dataService.getISTransactionsForTxBlock( parseInt(blockNum) ); latestTxBlockNum = await dataService.getISBlockNum(); } else { txBlockObj = await dataService.getTxBlockObj(parseInt(blockNum)); latestTxBlockNum = await dataService.getNumTxBlocks(); try { txBlockTxns = await dataService.getTransactionsForTxBlock( parseInt(blockNum) ); } catch (e) { console.log(e); } } if (txBlockObj) setTxBlockObj(txBlockObj); if (txBlockTxns) setTxBlockTxns(txBlockTxns); if (latestTxBlockNum) setLatestTxBlockNum(latestTxBlockNum); } catch (e) { console.error(e); setError("An error occurred - please see console"); // TODO: Extract error and set error message // setError(e); } finally { setIsLoading(false); } }; getData(); return () => { setTxBlockObj(null); setTxBlockTxns(null); setLatestTxBlockNum(null); setError(null); }; }, [blockNum, dataService, isIsolatedServer]); const columns = useMemo( () => [ { id: "from-col", Header: "From", accessor: "txn.senderAddress", Cell: ({ value }: { value: string }) => ( {hexAddrToZilAddr(value)} ), }, { id: "to-col", Header: "To", Cell: ({ row }: { row: Row }) => { return ; }, }, { id: "hash-col", Header: "Hash", Cell: ({ row }: { row: Row }) => { console.log(row); return (
{row.original.txn.txParams.receipt && !row.original.txn.txParams.receipt.success && ( )} {"0x" + row.original.hash}
); }, }, { id: "amount-col", Header: "Amount", accessor: "txn.amount", Cell: ({ value }: { value: string }) => ( {qaToZil(value)}} >
{qaToZil(value, 10)}
), }, { id: "fee-col", Header: "Fee", accessor: "txn", Cell: ({ value }: { value: Transaction }) => { let fee = 0; if (value.txParams.receipt) { fee = Number(value.txParams.gasPrice) * value.txParams.receipt.cumulative_gas; } return ( {qaToZil(fee)}} >
{qaToZil(fee, 4)}
); }, }, ], [] ); const fetchData = useCallback( ({ pageIndex }: { pageIndex: number }) => { if (!txBlockTxns || !dataService) return; let receivedData: TransactionDetails[]; const getData = async () => { try { setIsLoadingTrans(true); receivedData = await dataService.getTransactionsDetails( txBlockTxns.slice(pageIndex * 10, pageIndex * 10 + 10) ); if (receivedData) setTransactionData(receivedData); } catch (e) { console.log(e); } finally { setIsLoadingTrans(false); } }; getData(); }, [dataService, txBlockTxns] ); return ( <> {isLoading ? (
) : null} {error ? ( ) : ( <> {latestTxBlockNum && (

Tx Block{" "} #{blockNum}

)} {txBlockObj && ( <>
Date: {timestampToDisplay(txBlockObj.header.Timestamp)} ( {timestampToTimeago(txBlockObj.header.Timestamp)})
Transactions: {txBlockObj.header.NumTxns}
Gas Limit: {txBlockObj.header.GasLimit}
Gas Used: {txBlockObj.header.GasUsed}
Txn Fees: {qaToZil(txBlockObj.header.TxnFees)}
Rewards Fees: {qaToZil(txBlockObj.header.Rewards)}
DS Block: {txBlockObj.header.DSBlockNum}
DS Leader: {pubKeyToZilAddr(txBlockObj.header.MinerPubKey)}
{txBlockObj.body.MicroBlockInfos.length > 0 && ( Micro Blocks {txBlockObj.body.MicroBlockInfos.map((x) => (
[{x.MicroBlockShardId}] {x.MicroBlockHash}
))}
)} )} {txBlockTxns && txBlockTxns.length > 0 && ( <>

Transactions

)} )} ); }; export default TxBlockDetailsPage;