mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Add route for signature request
This commit is contained in:
parent
706a6b0ad6
commit
5d1187c37b
@ -489,35 +489,47 @@ function signMsg (msgData) {
|
|||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
|
|
||||||
log.debug(`actions calling background.signMessage`)
|
return new Promise((resolve, reject) => {
|
||||||
background.signMessage(msgData, (err, newState) => {
|
log.debug(`actions calling background.signMessage`)
|
||||||
log.debug('signMessage called back')
|
background.signMessage(msgData, (err, newState) => {
|
||||||
dispatch(actions.updateMetamaskState(newState))
|
log.debug('signMessage called back')
|
||||||
dispatch(actions.hideLoadingIndication())
|
dispatch(actions.updateMetamaskState(newState))
|
||||||
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
|
||||||
if (err) log.error(err)
|
if (err) {
|
||||||
if (err) return dispatch(actions.displayWarning(err.message))
|
log.error(err)
|
||||||
|
dispatch(actions.displayWarning(err.message))
|
||||||
|
return reject(err)
|
||||||
|
}
|
||||||
|
|
||||||
dispatch(actions.completedTx(msgData.metamaskId))
|
dispatch(actions.completedTx(msgData.metamaskId))
|
||||||
|
return resolve(msgData)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function signPersonalMsg (msgData) {
|
function signPersonalMsg (msgData) {
|
||||||
log.debug('action - signPersonalMsg')
|
log.debug('action - signPersonalMsg')
|
||||||
return (dispatch) => {
|
return dispatch => {
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
|
|
||||||
log.debug(`actions calling background.signPersonalMessage`)
|
return new Promise((resolve, reject) => {
|
||||||
background.signPersonalMessage(msgData, (err, newState) => {
|
log.debug(`actions calling background.signPersonalMessage`)
|
||||||
log.debug('signPersonalMessage called back')
|
background.signPersonalMessage(msgData, (err, newState) => {
|
||||||
dispatch(actions.updateMetamaskState(newState))
|
log.debug('signPersonalMessage called back')
|
||||||
dispatch(actions.hideLoadingIndication())
|
dispatch(actions.updateMetamaskState(newState))
|
||||||
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
|
||||||
if (err) log.error(err)
|
if (err) {
|
||||||
if (err) return dispatch(actions.displayWarning(err.message))
|
log.error(err)
|
||||||
|
dispatch(actions.displayWarning(err.message))
|
||||||
|
return reject(err)
|
||||||
|
}
|
||||||
|
|
||||||
dispatch(actions.completedTx(msgData.metamaskId))
|
dispatch(actions.completedTx(msgData.metamaskId))
|
||||||
|
return resolve(msgData)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -527,16 +539,22 @@ function signTypedMsg (msgData) {
|
|||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
|
|
||||||
log.debug(`actions calling background.signTypedMessage`)
|
return new Promise((resolve, reject) => {
|
||||||
background.signTypedMessage(msgData, (err, newState) => {
|
log.debug(`actions calling background.signTypedMessage`)
|
||||||
log.debug('signTypedMessage called back')
|
background.signTypedMessage(msgData, (err, newState) => {
|
||||||
dispatch(actions.updateMetamaskState(newState))
|
log.debug('signTypedMessage called back')
|
||||||
dispatch(actions.hideLoadingIndication())
|
dispatch(actions.updateMetamaskState(newState))
|
||||||
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
|
||||||
if (err) log.error(err)
|
if (err) {
|
||||||
if (err) return dispatch(actions.displayWarning(err.message))
|
log.error(err)
|
||||||
|
dispatch(actions.displayWarning(err.message))
|
||||||
|
return reject(err)
|
||||||
|
}
|
||||||
|
|
||||||
dispatch(actions.completedTx(msgData.metamaskId))
|
dispatch(actions.completedTx(msgData.metamaskId))
|
||||||
|
return resolve(msgData)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -744,21 +762,66 @@ function txError (err) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cancelMsg (msgData) {
|
function cancelMsg (msgData) {
|
||||||
log.debug(`background.cancelMessage`)
|
return dispatch => {
|
||||||
background.cancelMessage(msgData.id)
|
dispatch(actions.showLoadingIndication())
|
||||||
return actions.completedTx(msgData.id)
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
log.debug(`background.cancelMessage`)
|
||||||
|
background.cancelMessage(msgData.id, (err, newState) => {
|
||||||
|
dispatch(actions.updateMetamaskState(newState))
|
||||||
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return reject(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(actions.completedTx(msgData.id))
|
||||||
|
return resolve(msgData)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancelPersonalMsg (msgData) {
|
function cancelPersonalMsg (msgData) {
|
||||||
const id = msgData.id
|
return dispatch => {
|
||||||
background.cancelPersonalMessage(id)
|
dispatch(actions.showLoadingIndication())
|
||||||
return actions.completedTx(id)
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const id = msgData.id
|
||||||
|
background.cancelPersonalMessage(id, (err, newState) => {
|
||||||
|
dispatch(actions.updateMetamaskState(newState))
|
||||||
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return reject(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(actions.completedTx(id))
|
||||||
|
return resolve(msgData)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancelTypedMsg (msgData) {
|
function cancelTypedMsg (msgData) {
|
||||||
const id = msgData.id
|
return dispatch => {
|
||||||
background.cancelTypedMessage(id)
|
dispatch(actions.showLoadingIndication())
|
||||||
return actions.completedTx(id)
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const id = msgData.id
|
||||||
|
background.cancelTypedMessage(id, (err, newState) => {
|
||||||
|
dispatch(actions.updateMetamaskState(newState))
|
||||||
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return reject(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(actions.completedTx(id))
|
||||||
|
return resolve(msgData)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancelTx (txData) {
|
function cancelTx (txData) {
|
||||||
|
@ -33,6 +33,7 @@ const RevealSeedPage = require('./components/pages/keychains/reveal-seed')
|
|||||||
const AddTokenPage = require('./components/pages/add-token')
|
const AddTokenPage = require('./components/pages/add-token')
|
||||||
const ImportAccountPage = require('./components/pages/import-account')
|
const ImportAccountPage = require('./components/pages/import-account')
|
||||||
const NoticeScreen = require('./components/pages/notice')
|
const NoticeScreen = require('./components/pages/notice')
|
||||||
|
const SignatureRequestPage = require('./components/pages/signature-request')
|
||||||
|
|
||||||
const Loading = require('./components/loading')
|
const Loading = require('./components/loading')
|
||||||
const NetworkIndicator = require('./components/network')
|
const NetworkIndicator = require('./components/network')
|
||||||
@ -60,6 +61,7 @@ const {
|
|||||||
CONFIRM_TRANSACTION_ROUTE,
|
CONFIRM_TRANSACTION_ROUTE,
|
||||||
INITIALIZE_ROUTE,
|
INITIALIZE_ROUTE,
|
||||||
NOTICE_ROUTE,
|
NOTICE_ROUTE,
|
||||||
|
SIGNATURE_REQUEST_ROUTE,
|
||||||
} = require('./routes')
|
} = require('./routes')
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
@ -112,6 +114,7 @@ class App extends Component {
|
|||||||
h(Authenticated, { path: SEND_ROUTE, exact, component: SendTransactionScreen2 }),
|
h(Authenticated, { path: SEND_ROUTE, exact, component: SendTransactionScreen2 }),
|
||||||
h(Authenticated, { path: ADD_TOKEN_ROUTE, exact, component: AddTokenPage }),
|
h(Authenticated, { path: ADD_TOKEN_ROUTE, exact, component: AddTokenPage }),
|
||||||
h(Authenticated, { path: IMPORT_ACCOUNT_ROUTE, exact, component: ImportAccountPage }),
|
h(Authenticated, { path: IMPORT_ACCOUNT_ROUTE, exact, component: ImportAccountPage }),
|
||||||
|
h(Authenticated, { path: SIGNATURE_REQUEST_ROUTE, exact, component: SignatureRequestPage }),
|
||||||
h(Authenticated, { path: DEFAULT_ROUTE, exact, component: this.renderPrimary }),
|
h(Authenticated, { path: DEFAULT_ROUTE, exact, component: this.renderPrimary }),
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
@ -356,6 +359,9 @@ class App extends Component {
|
|||||||
activeAddress,
|
activeAddress,
|
||||||
unapprovedTxs = {},
|
unapprovedTxs = {},
|
||||||
seedWords,
|
seedWords,
|
||||||
|
unapprovedMsgCount = 0,
|
||||||
|
unapprovedPersonalMsgCount = 0,
|
||||||
|
unapprovedTypedMessagesCount = 0,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
// seed words
|
// seed words
|
||||||
@ -386,6 +392,15 @@ class App extends Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unapproved messages
|
||||||
|
if (unapprovedTypedMessagesCount + unapprovedMsgCount + unapprovedPersonalMsgCount > 0) {
|
||||||
|
return h(Redirect, {
|
||||||
|
to: {
|
||||||
|
pathname: SIGNATURE_REQUEST_ROUTE,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// if (!props.noActiveNotices) {
|
// if (!props.noActiveNotices) {
|
||||||
// log.debug('rendering notice screen for unread notices.')
|
// log.debug('rendering notice screen for unread notices.')
|
||||||
// return h(NoticeScreen, {
|
// return h(NoticeScreen, {
|
||||||
@ -595,6 +610,9 @@ App.propTypes = {
|
|||||||
activeAddress: PropTypes.string,
|
activeAddress: PropTypes.string,
|
||||||
unapprovedTxs: PropTypes.object,
|
unapprovedTxs: PropTypes.object,
|
||||||
seedWords: PropTypes.string,
|
seedWords: PropTypes.string,
|
||||||
|
unapprovedMsgCount: PropTypes.number,
|
||||||
|
unapprovedPersonalMsgCount: PropTypes.number,
|
||||||
|
unapprovedTypedMessagesCount: PropTypes.number,
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
@ -617,6 +635,9 @@ function mapStateToProps (state) {
|
|||||||
unapprovedTxs,
|
unapprovedTxs,
|
||||||
lastUnreadNotice,
|
lastUnreadNotice,
|
||||||
lostAccounts,
|
lostAccounts,
|
||||||
|
unapprovedMsgCount,
|
||||||
|
unapprovedPersonalMsgCount,
|
||||||
|
unapprovedTypedMessagesCount,
|
||||||
} = metamask
|
} = metamask
|
||||||
const selected = address || Object.keys(accounts)[0]
|
const selected = address || Object.keys(accounts)[0]
|
||||||
|
|
||||||
@ -637,7 +658,9 @@ function mapStateToProps (state) {
|
|||||||
isOnboarding: Boolean(!noActiveNotices || seedWords || !isInitialized),
|
isOnboarding: Boolean(!noActiveNotices || seedWords || !isInitialized),
|
||||||
seedWords: state.metamask.seedWords,
|
seedWords: state.metamask.seedWords,
|
||||||
unapprovedTxs,
|
unapprovedTxs,
|
||||||
unapprovedMsgs: state.metamask.unapprovedMsgs,
|
unapprovedMsgCount,
|
||||||
|
unapprovedPersonalMsgCount,
|
||||||
|
unapprovedTypedMessagesCount,
|
||||||
menuOpen: state.appState.menuOpen,
|
menuOpen: state.appState.menuOpen,
|
||||||
network: state.metamask.network,
|
network: state.metamask.network,
|
||||||
provider: state.metamask.provider,
|
provider: state.metamask.provider,
|
||||||
|
321
ui/app/components/pages/signature-request.js
Normal file
321
ui/app/components/pages/signature-request.js
Normal file
@ -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(),
|
|
||||||
|
|
||||||
])
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -8,7 +8,6 @@ const actions = require('./actions')
|
|||||||
const txHelper = require('../lib/tx-helper')
|
const txHelper = require('../lib/tx-helper')
|
||||||
|
|
||||||
const PendingTx = require('./components/pending-tx')
|
const PendingTx = require('./components/pending-tx')
|
||||||
const SignatureRequest = require('./components/signature-request')
|
|
||||||
// const PendingMsg = require('./components/pending-msg')
|
// const PendingMsg = require('./components/pending-msg')
|
||||||
// const PendingPersonalMsg = require('./components/pending-personal-msg')
|
// const PendingPersonalMsg = require('./components/pending-personal-msg')
|
||||||
// const PendingTypedMsg = require('./components/pending-typed-msg')
|
// const PendingTypedMsg = require('./components/pending-typed-msg')
|
||||||
@ -21,6 +20,12 @@ module.exports = compose(
|
|||||||
)(ConfirmTxScreen)
|
)(ConfirmTxScreen)
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
|
const { metamask } = state
|
||||||
|
const {
|
||||||
|
unapprovedMsgCount,
|
||||||
|
unapprovedPersonalMsgCount,
|
||||||
|
} = metamask
|
||||||
|
|
||||||
return {
|
return {
|
||||||
identities: state.metamask.identities,
|
identities: state.metamask.identities,
|
||||||
accounts: state.metamask.accounts,
|
accounts: state.metamask.accounts,
|
||||||
@ -37,6 +42,8 @@ function mapStateToProps (state) {
|
|||||||
currentCurrency: state.metamask.currentCurrency,
|
currentCurrency: state.metamask.currentCurrency,
|
||||||
blockGasLimit: state.metamask.currentBlockGasLimit,
|
blockGasLimit: state.metamask.currentBlockGasLimit,
|
||||||
computedBalances: state.metamask.computedBalances,
|
computedBalances: state.metamask.computedBalances,
|
||||||
|
unapprovedMsgCount,
|
||||||
|
unapprovedPersonalMsgCount,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,27 +132,13 @@ ConfirmTxScreen.prototype.render = function () {
|
|||||||
function currentTxView (opts) {
|
function currentTxView (opts) {
|
||||||
log.info('rendering current tx view')
|
log.info('rendering current tx view')
|
||||||
const { txData } = opts
|
const { txData } = opts
|
||||||
const { txParams, msgParams } = txData
|
const { txParams } = txData
|
||||||
|
|
||||||
if (txParams) {
|
if (txParams) {
|
||||||
log.debug('txParams detected, rendering pending tx')
|
log.debug('txParams detected, rendering pending tx')
|
||||||
return h(PendingTx, opts)
|
return h(PendingTx, opts)
|
||||||
} else if (msgParams) {
|
|
||||||
log.debug('msgParams detected, rendering pending msg')
|
|
||||||
|
|
||||||
return h(SignatureRequest, opts)
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return h(Loading)
|
return h(Loading)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ const SEND_ROUTE = '/send'
|
|||||||
const CONFIRM_TRANSACTION_ROUTE = '/confirm-transaction'
|
const CONFIRM_TRANSACTION_ROUTE = '/confirm-transaction'
|
||||||
const INITIALIZE_ROUTE = '/initialize'
|
const INITIALIZE_ROUTE = '/initialize'
|
||||||
const NOTICE_ROUTE = '/notice'
|
const NOTICE_ROUTE = '/notice'
|
||||||
|
const SIGNATURE_REQUEST_ROUTE = '/signature-request'
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
DEFAULT_ROUTE,
|
DEFAULT_ROUTE,
|
||||||
@ -26,4 +27,5 @@ module.exports = {
|
|||||||
CONFIRM_TRANSACTION_ROUTE,
|
CONFIRM_TRANSACTION_ROUTE,
|
||||||
INITIALIZE_ROUTE,
|
INITIALIZE_ROUTE,
|
||||||
NOTICE_ROUTE,
|
NOTICE_ROUTE,
|
||||||
|
SIGNATURE_REQUEST_ROUTE,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user