parent
706a6b0ad6
commit
5d1187c37b
@ -0,0 +1,321 @@ |
|||||||
|
const { Component } = require('react') |
||||||
|
const h = require('react-hyperscript') |
||||||
|
const PropTypes = require('prop-types') |
||||||
|
const Identicon = require('../identicon') |
||||||
|
const { connect } = require('react-redux') |
||||||
|
const ethUtil = require('ethereumjs-util') |
||||||
|
const classnames = require('classnames') |
||||||
|
|
||||||
|
const AccountDropdownMini = require('../dropdowns/account-dropdown-mini') |
||||||
|
|
||||||
|
const actions = require('../../actions') |
||||||
|
const { conversionUtil } = require('../../conversion-util') |
||||||
|
const txHelper = require('../../../lib/tx-helper') |
||||||
|
const { DEFAULT_ROUTE } = require('../../routes') |
||||||
|
|
||||||
|
const { |
||||||
|
getSelectedAccount, |
||||||
|
getCurrentAccountWithSendEtherInfo, |
||||||
|
getSelectedAddress, |
||||||
|
accountsWithSendEtherInfoSelector, |
||||||
|
conversionRateSelector, |
||||||
|
} = require('../../selectors.js') |
||||||
|
|
||||||
|
class SignatureRequest extends Component { |
||||||
|
constructor (props) { |
||||||
|
super(props) |
||||||
|
|
||||||
|
this.state = { |
||||||
|
selectedAccount: props.selectedAccount, |
||||||
|
accountDropdownOpen: false, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
componentWillMount () { |
||||||
|
const { |
||||||
|
unapprovedMsgCount = 0, |
||||||
|
unapprovedPersonalMsgCount = 0, |
||||||
|
unapprovedTypedMessagesCount = 0, |
||||||
|
} = this.props |
||||||
|
|
||||||
|
if (unapprovedMsgCount + unapprovedPersonalMsgCount + unapprovedTypedMessagesCount < 1) { |
||||||
|
this.props.history.push(DEFAULT_ROUTE) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
renderHeader () { |
||||||
|
return h('div.request-signature__header', [ |
||||||
|
|
||||||
|
h('div.request-signature__header-background'), |
||||||
|
|
||||||
|
h('div.request-signature__header__text', 'Signature Request'), |
||||||
|
|
||||||
|
h('div.request-signature__header__tip-container', [ |
||||||
|
h('div.request-signature__header__tip'), |
||||||
|
]), |
||||||
|
|
||||||
|
]) |
||||||
|
} |
||||||
|
|
||||||
|
renderAccountDropdown () { |
||||||
|
const { |
||||||
|
selectedAccount, |
||||||
|
accountDropdownOpen, |
||||||
|
} = this.state |
||||||
|
|
||||||
|
const { accounts } = this.props |
||||||
|
|
||||||
|
return h('div.request-signature__account', [ |
||||||
|
|
||||||
|
h('div.request-signature__account-text', ['Account:']), |
||||||
|
|
||||||
|
h(AccountDropdownMini, { |
||||||
|
selectedAccount, |
||||||
|
accounts, |
||||||
|
onSelect: selectedAccount => this.setState({ selectedAccount }), |
||||||
|
dropdownOpen: accountDropdownOpen, |
||||||
|
openDropdown: () => this.setState({ accountDropdownOpen: true }), |
||||||
|
closeDropdown: () => this.setState({ accountDropdownOpen: false }), |
||||||
|
}), |
||||||
|
|
||||||
|
]) |
||||||
|
} |
||||||
|
|
||||||
|
renderBalance () { |
||||||
|
const { balance, conversionRate } = this.props |
||||||
|
|
||||||
|
const balanceInEther = conversionUtil(balance, { |
||||||
|
fromNumericBase: 'hex', |
||||||
|
toNumericBase: 'dec', |
||||||
|
fromDenomination: 'WEI', |
||||||
|
numberOfDecimals: 6, |
||||||
|
conversionRate, |
||||||
|
}) |
||||||
|
|
||||||
|
return h('div.request-signature__balance', [ |
||||||
|
|
||||||
|
h('div.request-signature__balance-text', ['Balance:']), |
||||||
|
|
||||||
|
h('div.request-signature__balance-value', `${balanceInEther} ETH`), |
||||||
|
|
||||||
|
]) |
||||||
|
} |
||||||
|
|
||||||
|
renderAccountInfo () { |
||||||
|
return h('div.request-signature__account-info', [ |
||||||
|
|
||||||
|
this.renderAccountDropdown(), |
||||||
|
|
||||||
|
this.renderRequestIcon(), |
||||||
|
|
||||||
|
this.renderBalance(), |
||||||
|
|
||||||
|
]) |
||||||
|
} |
||||||
|
|
||||||
|
renderRequestIcon () { |
||||||
|
const { requesterAddress } = this.props |
||||||
|
|
||||||
|
return h('div.request-signature__request-icon', [ |
||||||
|
h(Identicon, { |
||||||
|
diameter: 40, |
||||||
|
address: requesterAddress, |
||||||
|
}), |
||||||
|
]) |
||||||
|
} |
||||||
|
|
||||||
|
renderRequestInfo () { |
||||||
|
return h('div.request-signature__request-info', [ |
||||||
|
|
||||||
|
h('div.request-signature__headline', [ |
||||||
|
`Your signature is being requested`, |
||||||
|
]), |
||||||
|
|
||||||
|
]) |
||||||
|
} |
||||||
|
|
||||||
|
msgHexToText (hex) { |
||||||
|
try { |
||||||
|
const stripped = ethUtil.stripHexPrefix(hex) |
||||||
|
const buff = Buffer.from(stripped, 'hex') |
||||||
|
return buff.toString('utf8') |
||||||
|
} catch (e) { |
||||||
|
return hex |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
renderBody () { |
||||||
|
let rows = [] |
||||||
|
let notice = 'You are signing:' |
||||||
|
|
||||||
|
const { txData = {} } = this.props |
||||||
|
const { type, msgParams = {} } = txData |
||||||
|
const { data } = msgParams |
||||||
|
|
||||||
|
if (type === 'personal_sign') { |
||||||
|
rows = [{ name: 'Message', value: this.msgHexToText(data) }] |
||||||
|
} else if (type === 'eth_signTypedData') { |
||||||
|
rows = data |
||||||
|
} else if (type === 'eth_sign') { |
||||||
|
rows = [{ name: 'Message', value: data }] |
||||||
|
notice = `Signing this message can have
|
||||||
|
dangerous side effects. Only sign messages from |
||||||
|
sites you fully trust with your entire account. |
||||||
|
This dangerous method will be removed in a future version. ` |
||||||
|
} |
||||||
|
|
||||||
|
return h('div.request-signature__body', {}, [ |
||||||
|
|
||||||
|
this.renderAccountInfo(), |
||||||
|
|
||||||
|
this.renderRequestInfo(), |
||||||
|
|
||||||
|
h('div.request-signature__notice', { |
||||||
|
className: classnames({ |
||||||
|
'request-signature__notice': type === 'personal_sign' || type === 'eth_signTypedData', |
||||||
|
'request-signature__warning': type === 'eth_sign', |
||||||
|
}), |
||||||
|
}, [notice]), |
||||||
|
|
||||||
|
h('div.request-signature__rows', [ |
||||||
|
|
||||||
|
...rows.map(({ name, value }) => { |
||||||
|
return h('div.request-signature__row', [ |
||||||
|
h('div.request-signature__row-title', [`${name}:`]), |
||||||
|
h('div.request-signature__row-value', value), |
||||||
|
]) |
||||||
|
}), |
||||||
|
|
||||||
|
]), |
||||||
|
|
||||||
|
]) |
||||||
|
} |
||||||
|
|
||||||
|
renderFooter () { |
||||||
|
const { |
||||||
|
txData = {}, |
||||||
|
signPersonalMessage, |
||||||
|
signTypedMessage, |
||||||
|
cancelPersonalMessage, |
||||||
|
cancelTypedMessage, |
||||||
|
signMessage, |
||||||
|
cancelMessage, |
||||||
|
history, |
||||||
|
} = this.props |
||||||
|
|
||||||
|
const { type } = txData |
||||||
|
|
||||||
|
let cancel = () => Promise.resolve() |
||||||
|
let sign = () => Promise.resolve() |
||||||
|
const { msgParams: params = {}, id } = txData |
||||||
|
params.id = id |
||||||
|
params.metamaskId = id |
||||||
|
|
||||||
|
switch (type) { |
||||||
|
case 'personal_sign': |
||||||
|
cancel = () => cancelPersonalMessage(params) |
||||||
|
sign = () => signPersonalMessage(params) |
||||||
|
break |
||||||
|
case 'eth_signTypedData': |
||||||
|
cancel = () => cancelTypedMessage(params) |
||||||
|
sign = () => signTypedMessage(params) |
||||||
|
break |
||||||
|
case 'eth_sign': |
||||||
|
cancel = () => cancelMessage(params) |
||||||
|
sign = () => signMessage(params) |
||||||
|
break |
||||||
|
} |
||||||
|
|
||||||
|
return h('div.request-signature__footer', [ |
||||||
|
h('button.request-signature__footer__cancel-button', { |
||||||
|
onClick: () => { |
||||||
|
cancel().then(() => history.push(DEFAULT_ROUTE)) |
||||||
|
}, |
||||||
|
}, 'CANCEL'), |
||||||
|
h('button.request-signature__footer__sign-button', { |
||||||
|
onClick: () => { |
||||||
|
sign().then(() => history.push(DEFAULT_ROUTE)) |
||||||
|
}, |
||||||
|
}, 'SIGN'), |
||||||
|
]) |
||||||
|
} |
||||||
|
|
||||||
|
render () { |
||||||
|
return ( |
||||||
|
h('div.request-signature__container', [ |
||||||
|
|
||||||
|
this.renderHeader(), |
||||||
|
|
||||||
|
this.renderBody(), |
||||||
|
|
||||||
|
this.renderFooter(), |
||||||
|
|
||||||
|
]) |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
SignatureRequest.propTypes = { |
||||||
|
txData: PropTypes.object, |
||||||
|
signPersonalMessage: PropTypes.func, |
||||||
|
cancelPersonalMessage: PropTypes.func, |
||||||
|
signTypedMessage: PropTypes.func, |
||||||
|
cancelTypedMessage: PropTypes.func, |
||||||
|
signMessage: PropTypes.func, |
||||||
|
cancelMessage: PropTypes.func, |
||||||
|
requesterAddress: PropTypes.string, |
||||||
|
accounts: PropTypes.array, |
||||||
|
conversionRate: PropTypes.number, |
||||||
|
balance: PropTypes.string, |
||||||
|
selectedAccount: PropTypes.object, |
||||||
|
history: PropTypes.object, |
||||||
|
unapprovedMsgCount: PropTypes.number, |
||||||
|
unapprovedPersonalMsgCount: PropTypes.number, |
||||||
|
unapprovedTypedMessagesCount: PropTypes.number, |
||||||
|
} |
||||||
|
|
||||||
|
const mapStateToProps = state => { |
||||||
|
const { metamask } = state |
||||||
|
const { |
||||||
|
unapprovedTxs, |
||||||
|
unapprovedMsgs, |
||||||
|
unapprovedPersonalMsgs, |
||||||
|
unapprovedTypedMessages, |
||||||
|
network, |
||||||
|
unapprovedMsgCount, |
||||||
|
unapprovedPersonalMsgCount, |
||||||
|
unapprovedTypedMessagesCount, |
||||||
|
} = metamask |
||||||
|
const unconfTxList = txHelper( |
||||||
|
unapprovedTxs, |
||||||
|
unapprovedMsgs, |
||||||
|
unapprovedPersonalMsgs, |
||||||
|
unapprovedTypedMessages, |
||||||
|
network |
||||||
|
) || [] |
||||||
|
|
||||||
|
return { |
||||||
|
balance: getSelectedAccount(state).balance, |
||||||
|
selectedAccount: getCurrentAccountWithSendEtherInfo(state), |
||||||
|
selectedAddress: getSelectedAddress(state), |
||||||
|
accounts: accountsWithSendEtherInfoSelector(state), |
||||||
|
conversionRate: conversionRateSelector(state), |
||||||
|
unapprovedMsgCount, |
||||||
|
unapprovedPersonalMsgCount, |
||||||
|
unapprovedTypedMessagesCount, |
||||||
|
txData: unconfTxList[0] || {}, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => { |
||||||
|
return { |
||||||
|
signPersonalMessage: params => dispatch(actions.signPersonalMsg(params)), |
||||||
|
cancelPersonalMessage: params => dispatch(actions.cancelPersonalMsg(params)), |
||||||
|
signTypedMessage: params => dispatch(actions.signTypedMsg(params)), |
||||||
|
cancelTypedMessage: params => dispatch(actions.cancelTypedMsg(params)), |
||||||
|
signMessage: params => dispatch(actions.signMsg(params)), |
||||||
|
cancelMessage: params => dispatch(actions.cancelMsg(params)), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
module.exports = connect(mapStateToProps, mapDispatchToProps)(SignatureRequest) |
@ -1,253 +0,0 @@ |
|||||||
const Component = require('react').Component |
|
||||||
const h = require('react-hyperscript') |
|
||||||
const inherits = require('util').inherits |
|
||||||
const Identicon = require('./identicon') |
|
||||||
const connect = require('react-redux').connect |
|
||||||
const ethUtil = require('ethereumjs-util') |
|
||||||
const classnames = require('classnames') |
|
||||||
|
|
||||||
const AccountDropdownMini = require('./dropdowns/account-dropdown-mini') |
|
||||||
|
|
||||||
const actions = require('../actions') |
|
||||||
const { conversionUtil } = require('../conversion-util') |
|
||||||
|
|
||||||
const { |
|
||||||
getSelectedAccount, |
|
||||||
getCurrentAccountWithSendEtherInfo, |
|
||||||
getSelectedAddress, |
|
||||||
accountsWithSendEtherInfoSelector, |
|
||||||
conversionRateSelector, |
|
||||||
} = require('../selectors.js') |
|
||||||
|
|
||||||
function mapStateToProps (state) { |
|
||||||
return { |
|
||||||
balance: getSelectedAccount(state).balance, |
|
||||||
selectedAccount: getCurrentAccountWithSendEtherInfo(state), |
|
||||||
selectedAddress: getSelectedAddress(state), |
|
||||||
requester: null, |
|
||||||
requesterAddress: null, |
|
||||||
accounts: accountsWithSendEtherInfoSelector(state), |
|
||||||
conversionRate: conversionRateSelector(state), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) { |
|
||||||
return { |
|
||||||
goHome: () => dispatch(actions.goHome()), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(SignatureRequest) |
|
||||||
|
|
||||||
inherits(SignatureRequest, Component) |
|
||||||
function SignatureRequest (props) { |
|
||||||
Component.call(this) |
|
||||||
|
|
||||||
this.state = { |
|
||||||
selectedAccount: props.selectedAccount, |
|
||||||
accountDropdownOpen: false, |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
SignatureRequest.prototype.renderHeader = function () { |
|
||||||
return h('div.request-signature__header', [ |
|
||||||
|
|
||||||
h('div.request-signature__header-background'), |
|
||||||
|
|
||||||
h('div.request-signature__header__text', 'Signature Request'), |
|
||||||
|
|
||||||
h('div.request-signature__header__tip-container', [ |
|
||||||
h('div.request-signature__header__tip'), |
|
||||||
]), |
|
||||||
|
|
||||||
]) |
|
||||||
} |
|
||||||
|
|
||||||
SignatureRequest.prototype.renderAccountDropdown = function () { |
|
||||||
const { |
|
||||||
selectedAccount, |
|
||||||
accountDropdownOpen, |
|
||||||
} = this.state |
|
||||||
|
|
||||||
const { |
|
||||||
accounts, |
|
||||||
} = this.props |
|
||||||
|
|
||||||
return h('div.request-signature__account', [ |
|
||||||
|
|
||||||
h('div.request-signature__account-text', ['Account:']), |
|
||||||
|
|
||||||
h(AccountDropdownMini, { |
|
||||||
selectedAccount, |
|
||||||
accounts, |
|
||||||
onSelect: selectedAccount => this.setState({ selectedAccount }), |
|
||||||
dropdownOpen: accountDropdownOpen, |
|
||||||
openDropdown: () => this.setState({ accountDropdownOpen: true }), |
|
||||||
closeDropdown: () => this.setState({ accountDropdownOpen: false }), |
|
||||||
}), |
|
||||||
|
|
||||||
]) |
|
||||||
} |
|
||||||
|
|
||||||
SignatureRequest.prototype.renderBalance = function () { |
|
||||||
const { balance, conversionRate } = this.props |
|
||||||
|
|
||||||
const balanceInEther = conversionUtil(balance, { |
|
||||||
fromNumericBase: 'hex', |
|
||||||
toNumericBase: 'dec', |
|
||||||
fromDenomination: 'WEI', |
|
||||||
numberOfDecimals: 6, |
|
||||||
conversionRate, |
|
||||||
}) |
|
||||||
|
|
||||||
return h('div.request-signature__balance', [ |
|
||||||
|
|
||||||
h('div.request-signature__balance-text', ['Balance:']), |
|
||||||
|
|
||||||
h('div.request-signature__balance-value', `${balanceInEther} ETH`), |
|
||||||
|
|
||||||
]) |
|
||||||
} |
|
||||||
|
|
||||||
SignatureRequest.prototype.renderAccountInfo = function () { |
|
||||||
return h('div.request-signature__account-info', [ |
|
||||||
|
|
||||||
this.renderAccountDropdown(), |
|
||||||
|
|
||||||
this.renderRequestIcon(), |
|
||||||
|
|
||||||
this.renderBalance(), |
|
||||||
|
|
||||||
]) |
|
||||||
} |
|
||||||
|
|
||||||
SignatureRequest.prototype.renderRequestIcon = function () { |
|
||||||
const { requesterAddress } = this.props |
|
||||||
|
|
||||||
return h('div.request-signature__request-icon', [ |
|
||||||
h(Identicon, { |
|
||||||
diameter: 40, |
|
||||||
address: requesterAddress, |
|
||||||
}), |
|
||||||
]) |
|
||||||
} |
|
||||||
|
|
||||||
SignatureRequest.prototype.renderRequestInfo = function () { |
|
||||||
return h('div.request-signature__request-info', [ |
|
||||||
|
|
||||||
h('div.request-signature__headline', [ |
|
||||||
`Your signature is being requested`, |
|
||||||
]), |
|
||||||
|
|
||||||
]) |
|
||||||
} |
|
||||||
|
|
||||||
SignatureRequest.prototype.msgHexToText = function (hex) { |
|
||||||
try { |
|
||||||
const stripped = ethUtil.stripHexPrefix(hex) |
|
||||||
const buff = Buffer.from(stripped, 'hex') |
|
||||||
return buff.toString('utf8') |
|
||||||
} catch (e) { |
|
||||||
return hex |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
SignatureRequest.prototype.renderBody = function () { |
|
||||||
let rows |
|
||||||
let notice = 'You are signing:' |
|
||||||
|
|
||||||
const { txData } = this.props |
|
||||||
const { type, msgParams: { data } } = txData |
|
||||||
|
|
||||||
if (type === 'personal_sign') { |
|
||||||
rows = [{ name: 'Message', value: this.msgHexToText(data) }] |
|
||||||
} else if (type === 'eth_signTypedData') { |
|
||||||
rows = data |
|
||||||
} else if (type === 'eth_sign') { |
|
||||||
rows = [{ name: 'Message', value: data }] |
|
||||||
notice = `Signing this message can have
|
|
||||||
dangerous side effects. Only sign messages from |
|
||||||
sites you fully trust with your entire account. |
|
||||||
This dangerous method will be removed in a future version. ` |
|
||||||
} |
|
||||||
|
|
||||||
return h('div.request-signature__body', {}, [ |
|
||||||
|
|
||||||
this.renderAccountInfo(), |
|
||||||
|
|
||||||
this.renderRequestInfo(), |
|
||||||
|
|
||||||
h('div.request-signature__notice', { |
|
||||||
className: classnames({ |
|
||||||
'request-signature__notice': type === 'personal_sign' || type === 'eth_signTypedData', |
|
||||||
'request-signature__warning': type === 'eth_sign', |
|
||||||
}), |
|
||||||
}, [notice]), |
|
||||||
|
|
||||||
h('div.request-signature__rows', [ |
|
||||||
|
|
||||||
...rows.map(({ name, value }) => { |
|
||||||
return h('div.request-signature__row', [ |
|
||||||
h('div.request-signature__row-title', [`${name}:`]), |
|
||||||
h('div.request-signature__row-value', value), |
|
||||||
]) |
|
||||||
}), |
|
||||||
|
|
||||||
]), |
|
||||||
|
|
||||||
]) |
|
||||||
} |
|
||||||
|
|
||||||
SignatureRequest.prototype.renderFooter = function () { |
|
||||||
const { |
|
||||||
signPersonalMessage, |
|
||||||
signTypedMessage, |
|
||||||
cancelPersonalMessage, |
|
||||||
cancelTypedMessage, |
|
||||||
signMessage, |
|
||||||
cancelMessage, |
|
||||||
} = this.props |
|
||||||
|
|
||||||
const { txData } = this.props |
|
||||||
const { type } = txData |
|
||||||
|
|
||||||
let cancel |
|
||||||
let sign |
|
||||||
if (type === 'personal_sign') { |
|
||||||
cancel = cancelPersonalMessage |
|
||||||
sign = signPersonalMessage |
|
||||||
} else if (type === 'eth_signTypedData') { |
|
||||||
cancel = cancelTypedMessage |
|
||||||
sign = signTypedMessage |
|
||||||
} else if (type === 'eth_sign') { |
|
||||||
cancel = cancelMessage |
|
||||||
sign = signMessage |
|
||||||
} |
|
||||||
|
|
||||||
return h('div.request-signature__footer', [ |
|
||||||
h('button.request-signature__footer__cancel-button', { |
|
||||||
onClick: cancel, |
|
||||||
}, 'CANCEL'), |
|
||||||
h('button.request-signature__footer__sign-button', { |
|
||||||
onClick: sign, |
|
||||||
}, 'SIGN'), |
|
||||||
]) |
|
||||||
} |
|
||||||
|
|
||||||
SignatureRequest.prototype.render = function () { |
|
||||||
return ( |
|
||||||
|
|
||||||
h('div.request-signature__container', [ |
|
||||||
|
|
||||||
this.renderHeader(), |
|
||||||
|
|
||||||
this.renderBody(), |
|
||||||
|
|
||||||
this.renderFooter(), |
|
||||||
|
|
||||||
]) |
|
||||||
|
|
||||||
) |
|
||||||
|
|
||||||
} |
|
||||||
|
|
Loading…
Reference in new issue