{"size": 4032, "ext": "js", "max_stars_repo_path": "app/routes/popup/Transaction/components/SendTransaction/containers/SendTransaction.js", "max_stars_repo_name": "gnosis/safe-browser-extension", "max_stars_repo_stars_event_min_datetime": "2018-05-11T20:32:14.000Z", "max_stars_repo_stars_event_max_datetime": "2022-01-17T13:55:28.000Z", "max_issues_repo_path": "app/routes/popup/Transaction/components/SendTransaction/containers/SendTransaction.js", "max_issues_repo_name": "gnosis/safe-browser-extension", "max_issues_repo_issues_event_min_datetime": "2018-06-19T07:09:44.000Z", "max_issues_repo_issues_event_max_datetime": "2021-07-05T02:24:55.000Z", "max_forks_repo_path": "app/routes/popup/Transaction/components/SendTransaction/containers/SendTransaction.js", "max_forks_repo_name": "gnosis/safe-browser-extension", "max_forks_repo_forks_event_min_datetime": "2018-09-08T10:47:39.000Z", "max_forks_repo_forks_event_max_datetime": "2022-03-28T12:18:31.000Z"}
{"max_stars_count": 16, "max_issues_count": 60, "max_forks_count": 5, "avg_line_length": 24.8888888889, "max_line_length": 77, "alphanum_fraction": 0.6334325397}
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { ga } from 'utils/analytics'
import { TRANSACTIONS } from 'utils/analytics/events'
import selector from './selector'
import { getTxHash } from './gasData'
import { sendTransaction } from 'utils/sendNotifications'
import { getNonce } from 'logic/contracts/safeContracts'
import Layout from '../components/Layout'
import messages from '../../../../../../../extension/utils/messages'

class SendTransaction extends Component {
  constructor(props) {
    super(props)
    this.maxSeconds = 30
    this.state = {
      seconds: this.maxSeconds
    }
  }

  componentDidUpdate = () => {
    const { location, loadedData, reviewedTx } = this.props

    if (!location.state || !loadedData || reviewedTx) {
      return
    }
    if (location.state.action === 'confirmed') {
      this.handleConfirmTransaction()
    } else if (location.state.action === 'rejected') {
      this.handleRejectTransaction()
    }
  }

  handleConfirmTransaction = (resend) => {
    const { handleTransaction, transactionNumber } = this.props

    if (!handleTransaction()) {
      return
    }
    this.handleTransaction()

    chrome.runtime.sendMessage({
      msg: messages.MSG_PENDING_SENDTRANSACTION,
      position: transactionNumber
    })

    if (!resend) {
      ga([
        '_trackEvent',
        TRANSACTIONS,
        'click-confirm-transaction-from-dapp',
        'Confirm transaction from Dapp'
      ])
      return
    }
    ga([
      '_trackEvent',
      TRANSACTIONS,
      'click-re-send-transaction-from-dapp',
      'Re-send transaction from Dapp'
    ])
  }

  handleRejectTransaction = () => {
    this.handleRemoveTransaction()
    ga([
      '_trackEvent',
      TRANSACTIONS,
      'click-reject-transaction-from-dapp',
      'Reject transaction from Dapp'
    ])
  }

  handleMobileAppResponse = () => {
    chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
      if (request.msg === messages.MSG_RESOLVED_TRANSACTION) {
        clearInterval(this.timer)
        this.handleRemoveTransaction()
      }
    })
  }

  handleTransaction = async () => {
    const { transaction, ethAccount } = this.props

    this.setState({ seconds: this.maxSeconds })
    this.startCountdown()
    try {
      transaction.nonce = await getNonce(transaction)
      transaction.hash = await getTxHash(transaction)

      const response = await sendTransaction(
        ethAccount.getChecksumAddressString(),
        ethAccount.getPrivateKey(),
        transaction,
        transaction.from
      )
      if (response && response.status === 204) {
        this.handleMobileAppResponse()
      }
    } catch (err) {
      console.error(err)
    }
  }

  handleRemoveTransaction = async () => {
    const {
      transactionNumber,
      showTransaction,
      transactions,
      removeTransaction
    } = this.props

    if (transactions.txs.length === 1) {
      await removeTransaction(transactionNumber)
      window.close()
      return
    }

    const position = transactionNumber >= 1 ? transactionNumber - 1 : 0
    await removeTransaction(transactionNumber)
    showTransaction(position)
  }

  startCountdown = () => {
    this.timer = setInterval(this.countDown, 1000)
  }

  countDown = () => {
    const { seconds } = this.state
    if (seconds === 0) {
      clearInterval(this.timer)
      return
    }
    this.setState((prevState) => ({
      seconds: prevState.seconds - 1
    }))
  }

  componentWillUnmount = () => {
    clearInterval(this.timer)
  }

  render() {
    const { lockedAccount, loadedData, reviewedTx } = this.props
    const { seconds } = this.state

    return (
      <Layout
        lockedAccount={lockedAccount}
        loadedData={loadedData}
        reviewedTx={reviewedTx}
        seconds={seconds}
        handleConfirmTransaction={this.handleConfirmTransaction}
        handleRejectTransaction={this.handleRejectTransaction}
      />
    )
  }
}

export default connect(selector)(SendTransaction)
