nifty-wallet/old-ui/app/conf-tx.js

321 lines
11 KiB
JavaScript
Raw Normal View History

2020-04-23 12:30:28 -07:00
import PropTypes from 'prop-types'
import { Component } from 'react'
import { connect } from 'react-redux'
2017-11-14 08:04:23 -08:00
const h = require('react-hyperscript')
2017-11-15 09:35:18 -08:00
const actions = require('../../ui/app/actions')
const LoadingIndicator = require('./components/loading')
2017-11-14 08:04:23 -08:00
const txHelper = require('../lib/tx-helper')
2020-04-23 12:30:28 -07:00
import log from 'loglevel'
const { getCurrentKeyring, ifContractAcc } = require('./util')
2017-11-14 08:04:23 -08:00
const PendingTx = require('./components/pending-tx')
2018-10-30 07:30:51 -07:00
import PendingMsg from './components/pending-msg'
import PendingPersonalMsg from './components/pending-personal-msg'
import PendingTypedMsg from './components/pending-typed-msg'
2017-11-14 08:04:23 -08:00
const Loading = require('./components/loading')
2019-06-11 06:59:32 -07:00
const { DAI_CODE, POA_SOKOL_CODE, RSK_TESTNET_CODE, GOERLI_TESTNET_CODE } = require('../../app/scripts/controllers/network/enums')
const { getMetaMaskAccounts } = require('../../ui/app/selectors')
2020-04-23 12:30:28 -07:00
import BigNumber from 'bignumber.js'
class ConfirmTxScreen extends Component {
static propTypes = {
network: PropTypes.string,
identities: PropTypes.objectOf(PropTypes.object),
keyrings: PropTypes.array,
actions: PropTypes.objectOf(PropTypes.func),
isToken: PropTypes.bool,
isContractExecutionByUser: PropTypes.bool,
selectedAddress: PropTypes.string,
warning: PropTypes.string,
unapprovedTxs: PropTypes.object,
unapprovedMsgs: PropTypes.object,
unapprovedPersonalMsgs: PropTypes.object,
unapprovedTypedMessages: PropTypes.object,
pendingTxIndex: PropTypes.number,
blockGasLimit: PropTypes.string,
accounts: PropTypes.object,
currentCurrency: PropTypes.string,
computedBalances: PropTypes.object,
conversionRate: PropTypes.number,
tokenSymbol: PropTypes.string,
tokensToSend: PropTypes.objectOf(BigNumber),
tokensTransferTo: PropTypes.string,
2017-11-14 08:04:23 -08:00
}
2020-04-23 12:30:28 -07:00
render () {
const props = this.props
const { network, unapprovedTxs, currentCurrency, computedBalances,
unapprovedMsgs, unapprovedPersonalMsgs, unapprovedTypedMessages, blockGasLimit } = props
let { conversionRate } = props
const isTestnet = parseInt(network) === POA_SOKOL_CODE || parseInt(network) === RSK_TESTNET_CODE || parseInt(network) === GOERLI_TESTNET_CODE
const isDai = parseInt(network) === DAI_CODE
if (isTestnet) {
conversionRate = 0
} else if (isDai) {
conversionRate = 1
}
2017-11-14 08:04:23 -08:00
2020-04-23 12:30:28 -07:00
const unconfTxList = txHelper(unapprovedTxs, unapprovedMsgs, unapprovedPersonalMsgs, unapprovedTypedMessages, network)
const ind = props.pendingTxIndex || 0
const txData = unconfTxList[ind] || {}
const txParams = txData.params || {}
2017-11-14 08:04:23 -08:00
2020-04-23 12:30:28 -07:00
log.info(`rendering a combined ${unconfTxList.length} unconf msg & txs`)
if (unconfTxList.length === 0) return h(Loading, { isLoading: true })
2017-11-14 08:04:23 -08:00
2020-04-23 12:30:28 -07:00
const unconfTxListLength = unconfTxList.length
2017-11-14 08:04:23 -08:00
2020-04-23 12:30:28 -07:00
return (
2017-11-14 08:04:23 -08:00
2020-04-23 12:30:28 -07:00
h('.flex-column.flex-grow', {
style: {
width: '100%',
2018-01-23 01:12:50 -08:00
},
2020-04-23 12:30:28 -07:00
}, [
h(LoadingIndicator, {
isLoading: this.state ? !this.state.bypassLoadingScreen : txData.loadingDefaults,
loadingMessage: 'Estimating transaction cost…',
canBypass: true,
bypass: () => {
this.setState({bypassLoadingScreen: true})
},
}),
// subtitle and nav
warningIfExists(props.warning),
currentTxView({
// Properties
txData: txData,
key: txData.id,
selectedAddress: props.selectedAddress,
accounts: props.accounts,
identities: props.identities,
conversionRate,
currentCurrency,
blockGasLimit,
unconfTxListLength,
computedBalances,
network,
isToken: props.isToken,
tokenSymbol: props.tokenSymbol,
tokensToSend: props.tokensToSend,
tokensTransferTo: props.tokensTransferTo,
// Actions
buyEth: this.buyEth.bind(this, txParams.from || props.selectedAddress, props.isContractExecutionByUser),
sendTransaction: this.sendTransaction.bind(this),
cancelTransaction: this.cancelTransaction.bind(this, txData),
cancelAllTransactions: this.cancelAllTransactions.bind(this, unconfTxList),
signMessage: this.signMessage.bind(this, txData),
signPersonalMessage: this.signPersonalMessage.bind(this, txData),
signTypedMessage: this.signTypedMessage.bind(this, txData),
cancelMessage: this.cancelMessage.bind(this, txData),
cancelPersonalMessage: this.cancelPersonalMessage.bind(this, txData),
cancelTypedMessage: this.cancelTypedMessage.bind(this, txData),
}),
])
)
}
2017-11-14 08:04:23 -08:00
2020-04-23 12:30:28 -07:00
buyEth (address, isContractExecutionByUser, event) {
event.preventDefault()
this.props.actions.buyEthView(address, isContractExecutionByUser)
}
2017-11-14 08:04:23 -08:00
2020-04-23 12:30:28 -07:00
sendTransaction (txData, event) {
this.stopPropagation(event)
this.props.actions.updateAndApproveTx(txData)
this._checkIfContractExecutionAndUnlockContract(txData)
2017-11-14 08:04:23 -08:00
}
2020-04-23 12:30:28 -07:00
cancelTransaction (txData, event) {
this.stopPropagation(event)
event.preventDefault()
this.props.actions.cancelTx(txData)
this._checkIfContractExecutionAndUnlockContract(txData)
}
2017-11-14 08:04:23 -08:00
2020-04-23 12:30:28 -07:00
cancelAllTransactions (unconfTxList, event) {
this.stopPropagation(event)
event.preventDefault()
this.props.actions.cancelTxs(unconfTxList)
this._checkIfMultipleContractExecutionAndUnlockContract(unconfTxList)
}
2017-11-14 08:04:23 -08:00
2020-04-23 12:30:28 -07:00
signMessage (msgData, event) {
log.info('conf-tx.js: signing message')
const params = msgData.msgParams
params.metamaskId = msgData.id
this.stopPropagation(event)
this.props.actions.signMsg(params)
}
2017-11-14 08:04:23 -08:00
2020-04-23 12:30:28 -07:00
stopPropagation (event) {
if (event.stopPropagation) {
event.stopPropagation()
}
}
2017-11-14 08:04:23 -08:00
2020-04-23 12:30:28 -07:00
signPersonalMessage (msgData, event) {
log.info('conf-tx.js: signing personal message')
const params = msgData.msgParams
params.metamaskId = msgData.id
this.stopPropagation(event)
this.props.actions.signPersonalMsg(params)
}
2017-11-14 08:04:23 -08:00
2020-04-23 12:30:28 -07:00
signTypedMessage (msgData, event) {
log.info('conf-tx.js: signing typed message')
const params = msgData.msgParams
params.metamaskId = msgData.id
this.stopPropagation(event)
this.props.actions.signTypedMsg(params)
2017-11-14 08:04:23 -08:00
}
2020-04-23 12:30:28 -07:00
cancelMessage (msgData, event) {
log.info('canceling message')
this.stopPropagation(event)
this.props.actions.cancelMsg(msgData)
}
2017-11-14 08:04:23 -08:00
2020-04-23 12:30:28 -07:00
cancelPersonalMessage (msgData, event) {
log.info('canceling personal message')
this.stopPropagation(event)
this.props.actions.cancelPersonalMsg(msgData)
}
2017-11-14 08:04:23 -08:00
2020-04-23 12:30:28 -07:00
cancelTypedMessage (msgData, event) {
log.info('canceling typed message')
this.stopPropagation(event)
this.props.actions.cancelTypedMsg(msgData)
}
2017-11-14 08:04:23 -08:00
2020-04-23 12:30:28 -07:00
_checkIfMultipleContractExecutionAndUnlockContract (unconfTxList) {
const areTxsToOneContractFromTheList = unconfTxList.slice(0).reduce((res, txData, ind, unconfTxList) => {
if (txData.txParams.data && this.props.isContractExecutionByUser) {
const to = txData && txData.txParams && txData.txParams.to
const targetContractIsInTheList = Object.keys(this.props.accounts).some((acc) => acc === to)
if (targetContractIsInTheList && Object.keys(res).length === 0) {
res = { status: true, to }
} else if (res.status && res.to !== to) {
res = { status: false }
unconfTxList.splice(1)
}
} else {
res = { status: false }
unconfTxList.splice(1)
}
return res
}, {})
2017-11-14 08:04:23 -08:00
2020-04-23 12:30:28 -07:00
if (areTxsToOneContractFromTheList.status) {
this._unlockContract(areTxsToOneContractFromTheList.to)
}
}
2017-11-14 08:04:23 -08:00
2020-04-23 12:30:28 -07:00
_checkIfContractExecutionAndUnlockContract (txData) {
if (txData.txParams.data && this.props.isContractExecutionByUser) {
const to = txData && txData.txParams && txData.txParams.to
const targetContractIsInTheList = Object.keys(this.props.accounts).some((acc) => acc === to)
2020-04-23 12:30:28 -07:00
if (targetContractIsInTheList) {
this._unlockContract(to)
}
}
}
2020-04-23 12:30:28 -07:00
_unlockContract (to) {
const currentKeyring = getCurrentKeyring(to, this.props.network, this.props.keyrings, this.props.identities)
if (ifContractAcc(currentKeyring)) {
this.props.actions.showAccountDetail(to)
}
}
}
2020-04-23 12:30:28 -07:00
function currentTxView (opts) {
log.info('rendering current tx view')
const { txData } = opts
const { txParams, msgParams, type } = txData
if (txParams) {
log.debug('txParams detected, rendering pending tx')
return h(PendingTx, opts)
} else if (msgParams) {
log.debug('msgParams detected, rendering pending msg')
if (type === 'eth_sign') {
log.debug('rendering eth_sign message')
return h(PendingMsg, opts)
} else if (type === 'personal_sign') {
log.debug('rendering personal_sign message')
return h(PendingPersonalMsg, opts)
} else if (type === 'eth_signTypedData') {
log.debug('rendering eth_signTypedData message')
return h(PendingTypedMsg, opts)
}
}
}
2017-11-14 08:04:23 -08:00
function warningIfExists (warning) {
if (warning &&
// Do not display user rejections on this screen:
warning.indexOf('User denied transaction signature') === -1) {
return h('.error', {
style: {
margin: 'auto',
},
}, warning)
}
}
2020-04-23 12:30:28 -07:00
function mapStateToProps (state) {
const { metamask, appState } = state
const { screenParams, pendingTxIndex } = appState.currentView
return {
identities: metamask.identities,
accounts: getMetaMaskAccounts(state),
keyrings: metamask.keyrings,
selectedAddress: metamask.selectedAddress,
unapprovedTxs: metamask.unapprovedTxs,
unapprovedMsgs: metamask.unapprovedMsgs,
unapprovedPersonalMsgs: metamask.unapprovedPersonalMsgs,
unapprovedTypedMessages: metamask.unapprovedTypedMessages,
pendingTxIndex: pendingTxIndex || 0,
warning: appState.warning,
network: metamask.network,
provider: metamask.provider,
conversionRate: metamask.conversionRate,
currentCurrency: metamask.currentCurrency,
blockGasLimit: metamask.currentBlockGasLimit,
computedBalances: metamask.computedBalances,
isToken: (screenParams && screenParams.isToken),
tokenSymbol: (screenParams && screenParams.tokenSymbol),
tokensToSend: (screenParams && screenParams.tokensToSend),
tokensTransferTo: (screenParams && screenParams.tokensTransferTo),
isContractExecutionByUser: (screenParams && screenParams.isContractExecutionByUser),
}
}
function mapDispatchToProps (dispatch) {
return {
actions: {
buyEthView: (address, isContractExecutionByUser) => dispatch(actions.buyEthView(address, isContractExecutionByUser)),
updateAndApproveTx: (txData) => dispatch(actions.updateAndApproveTx(txData)),
cancelTx: (txData) => dispatch(actions.cancelTx(txData)),
cancelTxs: (unconfTxList) => dispatch(actions.cancelTxs(unconfTxList)),
signMsg: (params) => dispatch(actions.signMsg(params)),
signPersonalMsg: (params) => dispatch(actions.signPersonalMsg(params)),
signTypedMsg: (params) => dispatch(actions.signTypedMsg(params)),
cancelMsg: (msgData) => dispatch(actions.cancelMsg(msgData)),
cancelPersonalMsg: (msgData) => dispatch(actions.cancelPersonalMsg(msgData)),
cancelTypedMsg: (msgData) => dispatch(actions.cancelTypedMsg(msgData)),
showAccountDetail: (to) => dispatch(actions.showAccountDetail(to)),
},
}
}
module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmTxScreen)