1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-10-23 11:46:13 +02:00
metamask-extension/ui/app/components/pages/signature-request.js
2017-12-14 14:11:23 -08:00

322 lines
8.2 KiB
JavaScript

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)