/ common / components / TransactionStatus / TransactionDataTable.tsx
TransactionDataTable.tsx
  1  import React from 'react';
  2  
  3  import translate from 'translations';
  4  import { TransactionData, TransactionReceipt } from 'types/transactions';
  5  import { NetworkConfig } from 'types/network';
  6  import { Identicon, UnitDisplay, NewTabLink, Address, CodeBlock } from 'components/ui';
  7  import './TransactionDataTable.scss';
  8  
  9  interface TableRow {
 10    label: React.ReactElement<string> | string;
 11    data: React.ReactElement<string> | string | number | null;
 12  }
 13  
 14  const MaybeLink: React.SFC<{
 15    href: string | null | undefined | false;
 16    children: any; // Too many damn React element types
 17  }> = ({ href, children }) => {
 18    if (href) {
 19      return <NewTabLink href={href}>{children}</NewTabLink>;
 20    } else {
 21      return <React.Fragment>{children}</React.Fragment>;
 22    }
 23  };
 24  
 25  interface Props {
 26    data: TransactionData;
 27    receipt: TransactionReceipt | null;
 28    network: NetworkConfig;
 29  }
 30  
 31  const TransactionDataTable: React.SFC<Props> = ({ data, receipt, network }) => {
 32    const explorer: { [key: string]: string | false | null } = {};
 33    const hasInputData = data.input && data.input !== '0x';
 34  
 35    if (!network.isCustom) {
 36      explorer.tx = network.blockExplorer && network.blockExplorer.txUrl(data.hash);
 37      explorer.block =
 38        network.blockExplorer &&
 39        !!data.blockNumber &&
 40        network.blockExplorer.blockUrl(data.blockNumber);
 41      explorer.to = network.blockExplorer && network.blockExplorer.addressUrl(data.to);
 42      explorer.from = network.blockExplorer && network.blockExplorer.addressUrl(data.from);
 43      explorer.contract =
 44        network.blockExplorer &&
 45        receipt &&
 46        receipt.contractAddress &&
 47        network.blockExplorer.addressUrl(receipt.contractAddress);
 48    }
 49  
 50    let statusMsg = '';
 51    let statusType = '';
 52    let statusSeeMore = false;
 53    if (receipt) {
 54      if (receipt.status === 1) {
 55        statusMsg = 'SUCCESSFUL';
 56        statusType = 'success';
 57      } else if (receipt.status === 0) {
 58        statusMsg = 'FAILED';
 59        statusType = 'danger';
 60        statusSeeMore = true;
 61      } else {
 62        // Pre-byzantium transactions don't use status, and cannot have their
 63        // success determined over the JSON RPC api
 64        statusMsg = 'UNKNOWN';
 65        statusType = 'warning';
 66        statusSeeMore = true;
 67      }
 68    } else {
 69      statusMsg = 'PENDING';
 70      statusType = 'warning';
 71    }
 72  
 73    const rows: TableRow[] = [
 74      {
 75        label: translate('TX_STATUS'),
 76        data: (
 77          <React.Fragment>
 78            <strong className={`TxData-row-data-status is-${statusType}`}>{statusMsg}</strong>
 79            {statusSeeMore &&
 80              explorer.tx &&
 81              !network.isCustom && (
 82                <NewTabLink className="TxData-row-data-more" href={explorer.tx}>
 83                  (See more on {network.blockExplorer.name})
 84                </NewTabLink>
 85              )}
 86          </React.Fragment>
 87        )
 88      },
 89      {
 90        label: translate('X_TXHASH'),
 91        data: <MaybeLink href={explorer.tx}>{data.hash}</MaybeLink>
 92      },
 93      {
 94        label: translate('TX_BLOCK_NUMB'),
 95        data: receipt && <MaybeLink href={explorer.block}>{receipt.blockNumber}</MaybeLink>
 96      },
 97      {
 98        label: translate('OFFLINE_STEP1_LABEL_1'),
 99        data: (
100          <MaybeLink href={explorer.from}>
101            <Identicon address={data.from} size="26px" />
102            <Address address={data.from} />
103          </MaybeLink>
104        )
105      },
106      {
107        label: translate('OFFLINE_STEP2_LABEL_1'),
108        data: (
109          <MaybeLink href={explorer.to}>
110            <Identicon address={data.to} size="26px" />
111            <Address address={data.to} />
112          </MaybeLink>
113        )
114      },
115      {
116        label: translate('SEND_AMOUNT_SHORT'),
117        data: <UnitDisplay value={data.value} unit="ether" symbol={network.unit} />
118      },
119      {
120        label: translate('OFFLINE_STEP2_LABEL_3'),
121        data: <UnitDisplay value={data.gasPrice} unit="gwei" symbol="Gwei" />
122      },
123      {
124        label: translate('OFFLINE_STEP2_LABEL_4'),
125        data: <UnitDisplay value={data.gas} unit="wei" />
126      },
127      {
128        label: translate('TX_GAS_USED'),
129        data: receipt && <UnitDisplay value={receipt.gasUsed} unit="wei" />
130      },
131      {
132        label: translate('CONFIRM_TX_FEE'),
133        data: receipt && (
134          <UnitDisplay
135            value={receipt.gasUsed.mul(data.gasPrice)}
136            unit="ether"
137            symbol={network.unit}
138          />
139        )
140      },
141      {
142        label: translate('NEW_CONTRACT_ADDR'),
143        data: receipt &&
144          receipt.contractAddress && (
145            <MaybeLink href={explorer.contract}>
146              <Address address={receipt.contractAddress} />
147            </MaybeLink>
148          )
149      },
150      {
151        label: translate('OFFLINE_STEP2_LABEL_5'),
152        data: data.nonce
153      },
154      {
155        label: translate('TRANS_DATA'),
156        data: hasInputData ? <CodeBlock>{data.input}</CodeBlock> : null
157      }
158    ];
159  
160    const filteredRows = rows.filter(row => !!row.data);
161    return (
162      <table className="TxData table table-striped">
163        <tbody>
164          {filteredRows.map((row, idx) => (
165            <tr className="TxData-row" key={idx}>
166              <td className="TxData-row-label">{row.label}</td>
167              <td className="TxData-row-data">{row.data}</td>
168            </tr>
169          ))}
170        </tbody>
171      </table>
172    );
173  };
174  
175  export default TransactionDataTable;