<commit_before>import { Balance, TabbedHeader, CopyToClipboard } from "shared";
import { shell } from "electron";
import { transactionDetails } from "connectors";
import { SlateGrayButton } from "buttons";
import { addSpacingAroundText, tsToDate, reverseHash } from "helpers";
import { FormattedMessage as T, injectIntl, defineMessages } from "react-intl";
import { DecodedTransaction }  from "middleware/walletrpc/api_pb";
import "style/TxDetails.less";
import "style/Fonts.less";

const messages = defineMessages({
  Ticket:     { id: "transaction.type.ticket", defaultMessage: "Ticket" },
  Vote:       { id: "transaction.type.vote",   defaultMessage: "Vote" },
  Revocation: { id: "transaction.type.revoke", defaultMessage: "Revoke" }
});

const headerIcons = {
  in:         "plusBig",
  out:        "minusBig",
  transfer:   "walletGray",
  Ticket:     "ticketSmall",
  Vote:       "ticketSmall",
  Revocation: "ticketSmall",
};

function mapNonWalletOutput(output) {
  const address = output.getAddressesList()[0] || "[script]";

  const amount = output.getScriptClass() === DecodedTransaction.Output.ScriptClass.NULL_DATA
    ? "[null data]"
    : <Balance amount={output.getValue()} />;

  return {address, amount};
}

function mapNonWalletInput(input) {
  const address =
    reverseHash(Buffer.from(input.getPreviousTransactionHash()).toString("hex")) +
    ":" +
    input.getPreviousTransactionIndex();

  const amount = input.getAmountIn();

  return {address, amount};
}

const TxDetails = ({ routes, router,
                     decodedTransaction,
                     tx: {
                       txHash,
                       txUrl,
                       txHeight,
                       txType,
                       txInputs,
                       txOutputs,
                       txBlockHash,
                       txBlockUrl,
                       txAmount,
                       txFee,
                       txDirection,
                       txTimestamp,
                       rawTx
                     },
                     currentBlockHeight,
                     intl
                   }) => {
  const isConfirmed = !!txTimestamp;
  const icon = headerIcons[txType || txDirection];
  const subtitle = isConfirmed && <T id="txDetails.timestamp" m="{timestamp, date, medium} {timestamp, time, medium}" values={{ timestamp: tsToDate(txTimestamp) }}/>;
  const goBack = () => router.goBack();
  const openTxUrl = () => shell.openExternal(txUrl);
  const openBlockUrl = () => shell.openExternal(txBlockUrl);
  const title = txType ? intl.formatMessage(messages[txType]) :
    <div className="txdetails-header-title">
      <span className="bold">
        {txDirection === "in" ? "" : "-"}
      </span>
      <Balance title bold amount={txAmount}/>
    </div>;

  let nonWalletInputs = [];
  let nonWalletOutputs = [];
  if (decodedTransaction) {
    const walletOutputIndices = txOutputs.map(v => v.index);
    const walletInputIndices = txInputs.map(v => v.index);

    nonWalletInputs = decodedTransaction.transaction.getInputsList()
      .filter((v, i) => walletInputIndices.indexOf(i) === -1)
      .map(mapNonWalletInput);
    nonWalletOutputs = decodedTransaction.transaction.getOutputsList()
      .filter((v, i) => walletOutputIndices.indexOf(i) === -1)
      .map(mapNonWalletOutput);
  }
  const hasNonWalletIO = nonWalletInputs.length || nonWalletOutputs.length;

  return (
    <Aux>
      <TabbedHeader {...{ routes, icon, title, subtitle }}>
        <SlateGrayButton onClick={ goBack }><commit_msg>Add Unconfirmed subtitle (#1009)<commit_after>import { Balance, TabbedHeader, CopyToClipboard } from "shared";
import { shell } from "electron";
import { transactionDetails } from "connectors";
import { SlateGrayButton } from "buttons";
import { addSpacingAroundText, tsToDate, reverseHash } from "helpers";
import { FormattedMessage as T, injectIntl, defineMessages } from "react-intl";
import { DecodedTransaction }  from "middleware/walletrpc/api_pb";
import "style/TxDetails.less";
import "style/Fonts.less";

const messages = defineMessages({
  Ticket:     { id: "transaction.type.ticket", defaultMessage: "Ticket" },
  Vote:       { id: "transaction.type.vote",   defaultMessage: "Vote" },
  Revocation: { id: "transaction.type.revoke", defaultMessage: "Revoke" }
});

const headerIcons = {
  in:         "plusBig",
  out:        "minusBig",
  transfer:   "walletGray",
  Ticket:     "ticketSmall",
  Vote:       "ticketSmall",
  Revocation: "ticketSmall",
};

function mapNonWalletOutput(output) {
  const address = output.getAddressesList()[0] || "[script]";

  const amount = output.getScriptClass() === DecodedTransaction.Output.ScriptClass.NULL_DATA
    ? "[null data]"
    : <Balance amount={output.getValue()} />;

  return {address, amount};
}

function mapNonWalletInput(input) {
  const address =
    reverseHash(Buffer.from(input.getPreviousTransactionHash()).toString("hex")) +
    ":" +
    input.getPreviousTransactionIndex();

  const amount = input.getAmountIn();

  return {address, amount};
}

const TxDetails = ({ routes, router,
                     decodedTransaction,
                     tx: {
                       txHash,
                       txUrl,
                       txHeight,
                       txType,
                       txInputs,
                       txOutputs,
                       txBlockHash,
                       txBlockUrl,
                       txAmount,
                       txFee,
                       txDirection,
                       txTimestamp,
                       rawTx
                     },
                     currentBlockHeight,
                     intl
                   }) => {
  const isConfirmed = !!txTimestamp;
  const icon = headerIcons[txType || txDirection];
  const subtitle = isConfirmed ? <T id="txDetails.timestamp" m="{timestamp, date, medium} {timestamp, time, medium}" values={{ timestamp: tsToDate(txTimestamp) }}/> : <T id="txDetails.unConfirmed" m="Unconfirmed"/>;
  const goBack = () => router.goBack();
  const openTxUrl = () => shell.openExternal(txUrl);
  const openBlockUrl = () => shell.openExternal(txBlockUrl);
  const title = txType ? intl.formatMessage(messages[txType]) :
    <div className="txdetails-header-title">
      <span className="bold">
        {txDirection === "in" ? "" : "-"}
      </span>
      <Balance title bold amount={txAmount}/>
    </div>;

  let nonWalletInputs = [];
  let nonWalletOutputs = [];
  if (decodedTransaction) {
    const walletOutputIndices = txOutputs.map(v => v.index);
    const walletInputIndices = txInputs.map(v => v.index);

    nonWalletInputs = decodedTransaction.transaction.getInputsList()
      .filter((v, i) => walletInputIndices.indexOf(i) === -1)
      .map(mapNonWalletInput);
    nonWalletOutputs = decodedTransaction.transaction.getOutputsList()
      .filter((v, i) => walletOutputIndices.indexOf(i) === -1)
      .map(mapNonWalletOutput);
  }
  const hasNonWalletIO = nonWalletInputs.length || nonWalletOutputs.length;

  return (
    <Aux>
      <TabbedHeader {...{ routes, icon, title, subtitle }}>
        <SlateGrayButton onClick={ goBack }>
{'fraction_non_alphanumeric': 0.12897378694924708, 'fraction_numerical': 0.0013943112102621305, 'mean_word_length': 2.5580357142857144, 'pattern_counts': {'":': 2, '<': 24, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3201643', 'n_tokens_mistral': 2070, 'n_tokens_neox': 2033, 'n_words': 426}