|
|
|
@ -1,5 +1,5 @@ |
|
|
|
|
import PropTypes from 'prop-types' |
|
|
|
|
import React, { Component } from 'react' |
|
|
|
|
import { inherits } from 'util' |
|
|
|
|
import { connect } from 'react-redux' |
|
|
|
|
import { withRouter } from 'react-router-dom' |
|
|
|
|
import { compose } from 'recompose' |
|
|
|
@ -12,11 +12,6 @@ import SignatureRequestOriginal from '../../components/app/signature-request-ori |
|
|
|
|
import Loading from '../../components/ui/loading-screen' |
|
|
|
|
import { DEFAULT_ROUTE } from '../../helpers/constants/routes' |
|
|
|
|
|
|
|
|
|
export default compose( |
|
|
|
|
withRouter, |
|
|
|
|
connect(mapStateToProps) |
|
|
|
|
)(ConfirmTxScreen) |
|
|
|
|
|
|
|
|
|
function mapStateToProps (state) { |
|
|
|
|
const { metamask } = state |
|
|
|
|
const { |
|
|
|
@ -45,188 +40,213 @@ function mapStateToProps (state) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
inherits(ConfirmTxScreen, Component) |
|
|
|
|
function ConfirmTxScreen () { |
|
|
|
|
Component.call(this) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ConfirmTxScreen.prototype.getUnapprovedMessagesTotal = function () { |
|
|
|
|
const { |
|
|
|
|
unapprovedMsgCount = 0, |
|
|
|
|
unapprovedPersonalMsgCount = 0, |
|
|
|
|
unapprovedTypedMessagesCount = 0, |
|
|
|
|
} = this.props |
|
|
|
|
|
|
|
|
|
return unapprovedTypedMessagesCount + unapprovedMsgCount + unapprovedPersonalMsgCount |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ConfirmTxScreen.prototype.componentDidMount = function () { |
|
|
|
|
const { |
|
|
|
|
unapprovedTxs = {}, |
|
|
|
|
network, |
|
|
|
|
send, |
|
|
|
|
} = this.props |
|
|
|
|
const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network) |
|
|
|
|
|
|
|
|
|
if (unconfTxList.length === 0 && !send.to && this.getUnapprovedMessagesTotal() === 0) { |
|
|
|
|
this.props.history.push(DEFAULT_ROUTE) |
|
|
|
|
class ConfirmTxScreen extends Component { |
|
|
|
|
static propTypes = { |
|
|
|
|
unapprovedMsgCount: PropTypes.number, |
|
|
|
|
unapprovedPersonalMsgCount: PropTypes.number, |
|
|
|
|
unapprovedTypedMessagesCount: PropTypes.number, |
|
|
|
|
network: PropTypes.string, |
|
|
|
|
index: PropTypes.number, |
|
|
|
|
unapprovedTxs: PropTypes.object, |
|
|
|
|
unapprovedMsgs: PropTypes.object, |
|
|
|
|
unapprovedPersonalMsgs: PropTypes.object, |
|
|
|
|
unapprovedTypedMessages: PropTypes.object, |
|
|
|
|
match: PropTypes.shape({ |
|
|
|
|
params: PropTypes.shape({ |
|
|
|
|
id: PropTypes.number, |
|
|
|
|
}), |
|
|
|
|
}), |
|
|
|
|
|
|
|
|
|
selectedAddressTxList: PropTypes.array, |
|
|
|
|
currentCurrency: PropTypes.string, |
|
|
|
|
blockGasLimit: PropTypes.string, |
|
|
|
|
history: PropTypes.object, |
|
|
|
|
identities: PropTypes.object, |
|
|
|
|
dispatch: PropTypes.func.isRequired, |
|
|
|
|
send: PropTypes.shape({ |
|
|
|
|
to: PropTypes.string, |
|
|
|
|
}).isRequired, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ConfirmTxScreen.prototype.componentDidUpdate = function (prevProps) { |
|
|
|
|
const { |
|
|
|
|
unapprovedTxs = {}, |
|
|
|
|
network, |
|
|
|
|
selectedAddressTxList, |
|
|
|
|
send, |
|
|
|
|
history, |
|
|
|
|
match: { params: { id: transactionId } = {} }, |
|
|
|
|
} = this.props |
|
|
|
|
|
|
|
|
|
let prevTx |
|
|
|
|
|
|
|
|
|
if (transactionId) { |
|
|
|
|
prevTx = R.find(({ id }) => id + '' === transactionId)(selectedAddressTxList) |
|
|
|
|
} else { |
|
|
|
|
const { index: prevIndex, unapprovedTxs: prevUnapprovedTxs } = prevProps |
|
|
|
|
const prevUnconfTxList = txHelper(prevUnapprovedTxs, {}, {}, {}, network) |
|
|
|
|
const prevTxData = prevUnconfTxList[prevIndex] || {} |
|
|
|
|
prevTx = selectedAddressTxList.find(({ id }) => id === prevTxData.id) || {} |
|
|
|
|
getUnapprovedMessagesTotal () { |
|
|
|
|
const { |
|
|
|
|
unapprovedMsgCount = 0, |
|
|
|
|
unapprovedPersonalMsgCount = 0, |
|
|
|
|
unapprovedTypedMessagesCount = 0, |
|
|
|
|
} = this.props |
|
|
|
|
|
|
|
|
|
return unapprovedTypedMessagesCount + unapprovedMsgCount + unapprovedPersonalMsgCount |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network) |
|
|
|
|
getTxData () { |
|
|
|
|
const { |
|
|
|
|
network, |
|
|
|
|
index, |
|
|
|
|
unapprovedTxs, |
|
|
|
|
unapprovedMsgs, |
|
|
|
|
unapprovedPersonalMsgs, |
|
|
|
|
unapprovedTypedMessages, |
|
|
|
|
match: { params: { id: transactionId } = {} }, |
|
|
|
|
} = this.props |
|
|
|
|
|
|
|
|
|
const unconfTxList = txHelper( |
|
|
|
|
unapprovedTxs, |
|
|
|
|
unapprovedMsgs, |
|
|
|
|
unapprovedPersonalMsgs, |
|
|
|
|
unapprovedTypedMessages, |
|
|
|
|
network |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
if (prevTx && prevTx.status === 'dropped') { |
|
|
|
|
this.props.dispatch(actions.showModal({ |
|
|
|
|
name: 'TRANSACTION_CONFIRMED', |
|
|
|
|
onSubmit: () => history.push(DEFAULT_ROUTE), |
|
|
|
|
})) |
|
|
|
|
log.info(`rendering a combined ${unconfTxList.length} unconf msgs & txs`) |
|
|
|
|
|
|
|
|
|
return |
|
|
|
|
return transactionId |
|
|
|
|
? R.find(({ id }) => id + '' === transactionId)(unconfTxList) |
|
|
|
|
: unconfTxList[index] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (unconfTxList.length === 0 && !send.to && this.getUnapprovedMessagesTotal() === 0) { |
|
|
|
|
this.props.history.push(DEFAULT_ROUTE) |
|
|
|
|
signatureSelect (type, version) { |
|
|
|
|
// Temporarily direct only v3 and v4 requests to new code.
|
|
|
|
|
if (type === 'eth_signTypedData' && (version === 'V3' || version === 'V4')) { |
|
|
|
|
return SignatureRequest |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return SignatureRequestOriginal |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ConfirmTxScreen.prototype.getTxData = function () { |
|
|
|
|
const { |
|
|
|
|
network, |
|
|
|
|
index, |
|
|
|
|
unapprovedTxs, |
|
|
|
|
unapprovedMsgs, |
|
|
|
|
unapprovedPersonalMsgs, |
|
|
|
|
unapprovedTypedMessages, |
|
|
|
|
match: { params: { id: transactionId } = {} }, |
|
|
|
|
} = this.props |
|
|
|
|
|
|
|
|
|
const unconfTxList = txHelper( |
|
|
|
|
unapprovedTxs, |
|
|
|
|
unapprovedMsgs, |
|
|
|
|
unapprovedPersonalMsgs, |
|
|
|
|
unapprovedTypedMessages, |
|
|
|
|
network |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
log.info(`rendering a combined ${unconfTxList.length} unconf msgs & txs`) |
|
|
|
|
|
|
|
|
|
return transactionId |
|
|
|
|
? R.find(({ id }) => id + '' === transactionId)(unconfTxList) |
|
|
|
|
: unconfTxList[index] |
|
|
|
|
} |
|
|
|
|
signMessage (msgData, event) { |
|
|
|
|
log.info('conf-tx.js: signing message') |
|
|
|
|
const params = msgData.msgParams |
|
|
|
|
params.metamaskId = msgData.id |
|
|
|
|
this.stopPropagation(event) |
|
|
|
|
return this.props.dispatch(actions.signMsg(params)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ConfirmTxScreen.prototype.signatureSelect = function (type, version) { |
|
|
|
|
// Temporarily direct only v3 and v4 requests to new code.
|
|
|
|
|
if (type === 'eth_signTypedData' && (version === 'V3' || version === 'V4')) { |
|
|
|
|
return SignatureRequest |
|
|
|
|
stopPropagation (event) { |
|
|
|
|
if (event.stopPropagation) { |
|
|
|
|
event.stopPropagation() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return SignatureRequestOriginal |
|
|
|
|
} |
|
|
|
|
signPersonalMessage (msgData, event) { |
|
|
|
|
log.info('conf-tx.js: signing personal message') |
|
|
|
|
const params = msgData.msgParams |
|
|
|
|
params.metamaskId = msgData.id |
|
|
|
|
this.stopPropagation(event) |
|
|
|
|
return this.props.dispatch(actions.signPersonalMsg(params)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ConfirmTxScreen.prototype.render = function () { |
|
|
|
|
const { |
|
|
|
|
currentCurrency, |
|
|
|
|
blockGasLimit, |
|
|
|
|
conversionRate, |
|
|
|
|
} = this.props |
|
|
|
|
signTypedMessage (msgData, event) { |
|
|
|
|
log.info('conf-tx.js: signing typed message') |
|
|
|
|
const params = msgData.msgParams |
|
|
|
|
params.metamaskId = msgData.id |
|
|
|
|
this.stopPropagation(event) |
|
|
|
|
return this.props.dispatch(actions.signTypedMsg(params)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const txData = this.getTxData() || {} |
|
|
|
|
const { msgParams, type, msgParams: { version } } = txData |
|
|
|
|
log.debug('msgParams detected, rendering pending msg') |
|
|
|
|
cancelMessage (msgData, event) { |
|
|
|
|
log.info('canceling message') |
|
|
|
|
this.stopPropagation(event) |
|
|
|
|
return this.props.dispatch(actions.cancelMsg(msgData)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!msgParams) { |
|
|
|
|
return ( |
|
|
|
|
<Loading /> |
|
|
|
|
) |
|
|
|
|
cancelPersonalMessage (msgData, event) { |
|
|
|
|
log.info('canceling personal message') |
|
|
|
|
this.stopPropagation(event) |
|
|
|
|
return this.props.dispatch(actions.cancelPersonalMsg(msgData)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const SigComponent = this.signatureSelect(type, version) |
|
|
|
|
return ( |
|
|
|
|
<SigComponent |
|
|
|
|
txData={txData} |
|
|
|
|
key={txData.id} |
|
|
|
|
selectedAddress={this.props.selectedAddress} |
|
|
|
|
accounts={this.props.accounts} |
|
|
|
|
identities={this.props.identities} |
|
|
|
|
conversionRate={conversionRate} |
|
|
|
|
currentCurrency={currentCurrency} |
|
|
|
|
blockGasLimit={blockGasLimit} |
|
|
|
|
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)} |
|
|
|
|
/> |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
cancelTypedMessage (msgData, event) { |
|
|
|
|
log.info('canceling typed message') |
|
|
|
|
this.stopPropagation(event) |
|
|
|
|
return this.props.dispatch(actions.cancelTypedMsg(msgData)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ConfirmTxScreen.prototype.signMessage = function (msgData, event) { |
|
|
|
|
log.info('conf-tx.js: signing message') |
|
|
|
|
const params = msgData.msgParams |
|
|
|
|
params.metamaskId = msgData.id |
|
|
|
|
this.stopPropagation(event) |
|
|
|
|
return this.props.dispatch(actions.signMsg(params)) |
|
|
|
|
} |
|
|
|
|
componentDidMount () { |
|
|
|
|
const { |
|
|
|
|
unapprovedTxs = {}, |
|
|
|
|
network, |
|
|
|
|
send, |
|
|
|
|
} = this.props |
|
|
|
|
const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network) |
|
|
|
|
|
|
|
|
|
if (unconfTxList.length === 0 && !send.to && this.getUnapprovedMessagesTotal() === 0) { |
|
|
|
|
this.props.history.push(DEFAULT_ROUTE) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ConfirmTxScreen.prototype.stopPropagation = function (event) { |
|
|
|
|
if (event.stopPropagation) { |
|
|
|
|
event.stopPropagation() |
|
|
|
|
componentDidUpdate (prevProps) { |
|
|
|
|
const { |
|
|
|
|
unapprovedTxs = {}, |
|
|
|
|
network, |
|
|
|
|
selectedAddressTxList, |
|
|
|
|
send, |
|
|
|
|
history, |
|
|
|
|
match: { params: { id: transactionId } = {} }, |
|
|
|
|
} = this.props |
|
|
|
|
|
|
|
|
|
let prevTx |
|
|
|
|
|
|
|
|
|
if (transactionId) { |
|
|
|
|
prevTx = R.find(({ id }) => id + '' === transactionId)(selectedAddressTxList) |
|
|
|
|
} else { |
|
|
|
|
const { index: prevIndex, unapprovedTxs: prevUnapprovedTxs } = prevProps |
|
|
|
|
const prevUnconfTxList = txHelper(prevUnapprovedTxs, {}, {}, {}, network) |
|
|
|
|
const prevTxData = prevUnconfTxList[prevIndex] || {} |
|
|
|
|
prevTx = selectedAddressTxList.find(({ id }) => id === prevTxData.id) || {} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network) |
|
|
|
|
|
|
|
|
|
if (prevTx && prevTx.status === 'dropped') { |
|
|
|
|
this.props.dispatch(actions.showModal({ |
|
|
|
|
name: 'TRANSACTION_CONFIRMED', |
|
|
|
|
onSubmit: () => history.push(DEFAULT_ROUTE), |
|
|
|
|
})) |
|
|
|
|
|
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (unconfTxList.length === 0 && !send.to && this.getUnapprovedMessagesTotal() === 0) { |
|
|
|
|
this.props.history.push(DEFAULT_ROUTE) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ConfirmTxScreen.prototype.signPersonalMessage = function (msgData, event) { |
|
|
|
|
log.info('conf-tx.js: signing personal message') |
|
|
|
|
const params = msgData.msgParams |
|
|
|
|
params.metamaskId = msgData.id |
|
|
|
|
this.stopPropagation(event) |
|
|
|
|
return this.props.dispatch(actions.signPersonalMsg(params)) |
|
|
|
|
} |
|
|
|
|
render () { |
|
|
|
|
const { |
|
|
|
|
currentCurrency, |
|
|
|
|
blockGasLimit, |
|
|
|
|
} = this.props |
|
|
|
|
|
|
|
|
|
ConfirmTxScreen.prototype.signTypedMessage = function (msgData, event) { |
|
|
|
|
log.info('conf-tx.js: signing typed message') |
|
|
|
|
const params = msgData.msgParams |
|
|
|
|
params.metamaskId = msgData.id |
|
|
|
|
this.stopPropagation(event) |
|
|
|
|
return this.props.dispatch(actions.signTypedMsg(params)) |
|
|
|
|
} |
|
|
|
|
const txData = this.getTxData() || {} |
|
|
|
|
const { msgParams, type, msgParams: { version } } = txData |
|
|
|
|
log.debug('msgParams detected, rendering pending msg') |
|
|
|
|
|
|
|
|
|
ConfirmTxScreen.prototype.cancelMessage = function (msgData, event) { |
|
|
|
|
log.info('canceling message') |
|
|
|
|
this.stopPropagation(event) |
|
|
|
|
return this.props.dispatch(actions.cancelMsg(msgData)) |
|
|
|
|
} |
|
|
|
|
if (!msgParams) { |
|
|
|
|
return ( |
|
|
|
|
<Loading /> |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ConfirmTxScreen.prototype.cancelPersonalMessage = function (msgData, event) { |
|
|
|
|
log.info('canceling personal message') |
|
|
|
|
this.stopPropagation(event) |
|
|
|
|
return this.props.dispatch(actions.cancelPersonalMsg(msgData)) |
|
|
|
|
const SigComponent = this.signatureSelect(type, version) |
|
|
|
|
return ( |
|
|
|
|
<SigComponent |
|
|
|
|
txData={txData} |
|
|
|
|
key={txData.id} |
|
|
|
|
identities={this.props.identities} |
|
|
|
|
currentCurrency={currentCurrency} |
|
|
|
|
blockGasLimit={blockGasLimit} |
|
|
|
|
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)} |
|
|
|
|
/> |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ConfirmTxScreen.prototype.cancelTypedMessage = function (msgData, event) { |
|
|
|
|
log.info('canceling typed message') |
|
|
|
|
this.stopPropagation(event) |
|
|
|
|
return this.props.dispatch(actions.cancelTypedMsg(msgData)) |
|
|
|
|
} |
|
|
|
|
export default compose( |
|
|
|
|
withRouter, |
|
|
|
|
connect(mapStateToProps) |
|
|
|
|
)(ConfirmTxScreen) |
|
|
|
|