mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Merge branch 'master' into i#1032
This commit is contained in:
commit
af5ad218e2
@ -2,6 +2,7 @@ const EventEmitter = require('events')
|
|||||||
const ObservableStore = require('obs-store')
|
const ObservableStore = require('obs-store')
|
||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
const createId = require('./random-id')
|
const createId = require('./random-id')
|
||||||
|
const hexRe = /^[0-9A-Fa-f]+$/g
|
||||||
|
|
||||||
|
|
||||||
module.exports = class PersonalMessageManager extends EventEmitter{
|
module.exports = class PersonalMessageManager extends EventEmitter{
|
||||||
@ -24,7 +25,8 @@ module.exports = class PersonalMessageManager extends EventEmitter{
|
|||||||
}
|
}
|
||||||
|
|
||||||
addUnapprovedMessage (msgParams) {
|
addUnapprovedMessage (msgParams) {
|
||||||
msgParams.data = normalizeMsgData(msgParams.data)
|
log.debug(`PersonalMessageManager addUnapprovedMessage: ${JSON.stringify(msgParams)}`)
|
||||||
|
msgParams.data = this.normalizeMsgData(msgParams.data)
|
||||||
// create txData obj with parameters and meta data
|
// create txData obj with parameters and meta data
|
||||||
var time = (new Date()).getTime()
|
var time = (new Date()).getTime()
|
||||||
var msgId = createId()
|
var msgId = createId()
|
||||||
@ -106,14 +108,18 @@ module.exports = class PersonalMessageManager extends EventEmitter{
|
|||||||
this.emit('updateBadge')
|
this.emit('updateBadge')
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
normalizeMsgData(data) {
|
||||||
|
try {
|
||||||
|
const stripped = ethUtil.stripHexPrefix(data)
|
||||||
|
if (stripped.match(hexRe)) {
|
||||||
|
return ethUtil.addHexPrefix(stripped)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
log.debug(`Message was not hex encoded, interpreting as utf8.`)
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeMsgData(data) {
|
|
||||||
if (data.slice(0, 2) === '0x') {
|
|
||||||
// data is already hex
|
|
||||||
return data
|
|
||||||
} else {
|
|
||||||
// data is unicode, convert to hex
|
|
||||||
return ethUtil.bufferToHex(new Buffer(data, 'utf8'))
|
return ethUtil.bufferToHex(new Buffer(data, 'utf8'))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,14 +414,14 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
self.sendUpdate()
|
self.sendUpdate()
|
||||||
self.opts.showUnapprovedTx(txMeta)
|
self.opts.showUnapprovedTx(txMeta)
|
||||||
// listen for tx completion (success, fail)
|
// listen for tx completion (success, fail)
|
||||||
self.txManager.once(`${txMeta.id}:finished`, (status) => {
|
self.txManager.once(`${txMeta.id}:finished`, (completedTx) => {
|
||||||
switch (status) {
|
switch (completedTx.status) {
|
||||||
case 'submitted':
|
case 'submitted':
|
||||||
return cb(null, txMeta.hash)
|
return cb(null, completedTx.hash)
|
||||||
case 'rejected':
|
case 'rejected':
|
||||||
return cb(new Error('MetaMask Tx Signature: User denied transaction signature.'))
|
return cb(new Error('MetaMask Tx Signature: User denied transaction signature.'))
|
||||||
default:
|
default:
|
||||||
return cb(new Error(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(txMeta.txParams)}`))
|
return cb(new Error(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(completedTx.txParams)}`))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -353,7 +353,7 @@ module.exports = class TransactionManager extends EventEmitter {
|
|||||||
txMeta.status = status
|
txMeta.status = status
|
||||||
this.emit(`${txMeta.id}:${status}`, txId)
|
this.emit(`${txMeta.id}:${status}`, txId)
|
||||||
if (status === 'submitted' || status === 'rejected') {
|
if (status === 'submitted' || status === 'rejected') {
|
||||||
this.emit(`${txMeta.id}:finished`, status)
|
this.emit(`${txMeta.id}:finished`, txMeta)
|
||||||
}
|
}
|
||||||
this.updateTx(txMeta)
|
this.updateTx(txMeta)
|
||||||
this.emit('updateBadge')
|
this.emit('updateBadge')
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
"eth-lightwallet": "^2.3.3",
|
"eth-lightwallet": "^2.3.3",
|
||||||
"eth-query": "^1.0.3",
|
"eth-query": "^1.0.3",
|
||||||
"eth-sig-util": "^1.1.1",
|
"eth-sig-util": "^1.1.1",
|
||||||
"eth-simple-keyring": "^1.1.0",
|
"eth-simple-keyring": "^1.1.1",
|
||||||
"ethereumjs-tx": "^1.0.0",
|
"ethereumjs-tx": "^1.0.0",
|
||||||
"ethereumjs-util": "ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9",
|
"ethereumjs-util": "ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9",
|
||||||
"ethereumjs-wallet": "^0.6.0",
|
"ethereumjs-wallet": "^0.6.0",
|
||||||
@ -109,7 +109,7 @@
|
|||||||
"valid-url": "^1.0.9",
|
"valid-url": "^1.0.9",
|
||||||
"vreme": "^3.0.2",
|
"vreme": "^3.0.2",
|
||||||
"web3": "0.18.2",
|
"web3": "0.18.2",
|
||||||
"web3-provider-engine": "^9.1.0",
|
"web3-provider-engine": "^9.2.1",
|
||||||
"web3-stream-provider": "^2.0.6",
|
"web3-stream-provider": "^2.0.6",
|
||||||
"xtend": "^4.0.1"
|
"xtend": "^4.0.1"
|
||||||
},
|
},
|
||||||
|
25
test/unit/components/binary-renderer-test.js
Normal file
25
test/unit/components/binary-renderer-test.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
var assert = require('assert')
|
||||||
|
var BinaryRenderer = require('../../../ui/app/components/binary-renderer')
|
||||||
|
|
||||||
|
describe('BinaryRenderer', function() {
|
||||||
|
|
||||||
|
let binaryRenderer
|
||||||
|
const message = 'Hello, world!'
|
||||||
|
const buffer = new Buffer(message, 'utf8')
|
||||||
|
const hex = buffer.toString('hex')
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
binaryRenderer = new BinaryRenderer()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('recovers message', function() {
|
||||||
|
const result = binaryRenderer.hexToText(hex)
|
||||||
|
assert.equal(result, message)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
it('recovers message with hex prefix', function() {
|
||||||
|
const result = binaryRenderer.hexToText('0x' + hex)
|
||||||
|
assert.equal(result, message)
|
||||||
|
})
|
||||||
|
})
|
@ -4,7 +4,7 @@ const EventEmitter = require('events')
|
|||||||
|
|
||||||
const PersonalMessageManager = require('../../app/scripts/lib/personal-message-manager')
|
const PersonalMessageManager = require('../../app/scripts/lib/personal-message-manager')
|
||||||
|
|
||||||
describe('Transaction Manager', function() {
|
describe('Personal Message Manager', function() {
|
||||||
let messageManager
|
let messageManager
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
@ -86,4 +86,25 @@ describe('Transaction Manager', function() {
|
|||||||
assert.equal(messageManager.getMsg('2').status, 'approved')
|
assert.equal(messageManager.getMsg('2').status, 'approved')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('#normalizeMsgData', function() {
|
||||||
|
it('converts text to a utf8 hex string', function() {
|
||||||
|
var input = 'hello'
|
||||||
|
var output = messageManager.normalizeMsgData(input)
|
||||||
|
assert.equal(output, '0x68656c6c6f', 'predictably hex encoded')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('tolerates a hex prefix', function() {
|
||||||
|
var input = '0x12'
|
||||||
|
var output = messageManager.normalizeMsgData(input)
|
||||||
|
assert.equal(output, '0x12', 'un modified')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('tolerates normal hex', function() {
|
||||||
|
var input = '12'
|
||||||
|
var output = messageManager.normalizeMsgData(input)
|
||||||
|
assert.equal(output, '0x12', 'adds prefix')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
43
ui/app/components/binary-renderer.js
Normal file
43
ui/app/components/binary-renderer.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
const Component = require('react').Component
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const inherits = require('util').inherits
|
||||||
|
const ethUtil = require('ethereumjs-util')
|
||||||
|
|
||||||
|
module.exports = BinaryRenderer
|
||||||
|
|
||||||
|
inherits(BinaryRenderer, Component)
|
||||||
|
function BinaryRenderer () {
|
||||||
|
Component.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryRenderer.prototype.render = function () {
|
||||||
|
const props = this.props
|
||||||
|
const { value } = props
|
||||||
|
const text = this.hexToText(value)
|
||||||
|
|
||||||
|
return (
|
||||||
|
h('textarea.font-small', {
|
||||||
|
readOnly: true,
|
||||||
|
style: {
|
||||||
|
width: '315px',
|
||||||
|
maxHeight: '210px',
|
||||||
|
resize: 'none',
|
||||||
|
border: 'none',
|
||||||
|
background: 'white',
|
||||||
|
padding: '3px',
|
||||||
|
},
|
||||||
|
defaultValue: text,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryRenderer.prototype.hexToText = function (hex) {
|
||||||
|
try {
|
||||||
|
const stripped = ethUtil.stripHexPrefix(hex)
|
||||||
|
const buff = Buffer.from(stripped, 'hex')
|
||||||
|
return buff.toString('utf8')
|
||||||
|
} catch (e) {
|
||||||
|
return hex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -39,15 +39,17 @@ HexAsDecimalInput.prototype.render = function () {
|
|||||||
},
|
},
|
||||||
}, [
|
}, [
|
||||||
h('input.ether-balance.ether-balance-amount', {
|
h('input.ether-balance.ether-balance-amount', {
|
||||||
|
type: 'number',
|
||||||
style: extend({
|
style: extend({
|
||||||
display: 'block',
|
display: 'block',
|
||||||
textAlign: 'right',
|
textAlign: 'right',
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
border: '1px solid #bdbdbd',
|
border: '1px solid #bdbdbd',
|
||||||
|
|
||||||
}, style),
|
}, style),
|
||||||
value: decimalValue,
|
value: decimalValue,
|
||||||
onChange: (event) => {
|
onChange: (event) => {
|
||||||
const hexString = hexify(event.target.value)
|
const hexString = (event.target.value === '') ? '' : hexify(event.target.value)
|
||||||
onChange(hexString)
|
onChange(hexString)
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@ -70,7 +72,11 @@ function hexify (decimalString) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function decimalize (input, toEth) {
|
function decimalize (input, toEth) {
|
||||||
const strippedInput = ethUtil.stripHexPrefix(input)
|
if (input === '') {
|
||||||
const inputBN = new BN(strippedInput, 'hex')
|
return ''
|
||||||
return inputBN.toString(10)
|
} else {
|
||||||
|
const strippedInput = ethUtil.stripHexPrefix(input)
|
||||||
|
const inputBN = new BN(strippedInput, 'hex')
|
||||||
|
return inputBN.toString(10)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ const h = require('react-hyperscript')
|
|||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
|
|
||||||
const AccountPanel = require('./account-panel')
|
const AccountPanel = require('./account-panel')
|
||||||
|
const BinaryRenderer = require('./binary-renderer')
|
||||||
|
|
||||||
module.exports = PendingMsgDetails
|
module.exports = PendingMsgDetails
|
||||||
|
|
||||||
@ -41,18 +42,7 @@ PendingMsgDetails.prototype.render = function () {
|
|||||||
// message data
|
// message data
|
||||||
h('div', [
|
h('div', [
|
||||||
h('label.font-small', { style: { display: 'block' } }, 'MESSAGE'),
|
h('label.font-small', { style: { display: 'block' } }, 'MESSAGE'),
|
||||||
h('textarea.font-small', {
|
h(BinaryRenderer, { value: data }),
|
||||||
readOnly: true,
|
|
||||||
style: {
|
|
||||||
width: '315px',
|
|
||||||
maxHeight: '210px',
|
|
||||||
resize: 'none',
|
|
||||||
border: 'none',
|
|
||||||
background: 'white',
|
|
||||||
padding: '3px',
|
|
||||||
},
|
|
||||||
defaultValue: data,
|
|
||||||
}),
|
|
||||||
]),
|
]),
|
||||||
|
|
||||||
])
|
])
|
||||||
|
@ -32,10 +32,8 @@ PTXP.render = function () {
|
|||||||
var account = props.accounts[address]
|
var account = props.accounts[address]
|
||||||
var balance = account ? account.balance : '0x0'
|
var balance = account ? account.balance : '0x0'
|
||||||
|
|
||||||
const gas = state.gas || txParams.gas
|
const gas = (state.gas === undefined) ? txParams.gas : state.gas
|
||||||
const gasPrice = state.gasPrice || txData.gasPrice
|
const gasPrice = (state.gasPrice === undefined) ? txData.gasPrice : state.gasPrice
|
||||||
const gasDefault = txParams.gas
|
|
||||||
const gasPriceDefault = txData.gasPrice
|
|
||||||
|
|
||||||
var txFee = state.txFee || txData.txFee || ''
|
var txFee = state.txFee || txData.txFee || ''
|
||||||
var maxCost = state.maxCost || txData.maxCost || ''
|
var maxCost = state.maxCost || txData.maxCost || ''
|
||||||
@ -131,11 +129,7 @@ PTXP.render = function () {
|
|||||||
},
|
},
|
||||||
onChange: (newHex) => {
|
onChange: (newHex) => {
|
||||||
log.info(`Gas limit changed to ${newHex}`)
|
log.info(`Gas limit changed to ${newHex}`)
|
||||||
if (newHex === '0x0') {
|
this.setState({ gas: newHex })
|
||||||
this.setState({gas: gasDefault})
|
|
||||||
} else {
|
|
||||||
this.setState({ gas: newHex })
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
@ -155,11 +149,7 @@ PTXP.render = function () {
|
|||||||
},
|
},
|
||||||
onChange: (newHex) => {
|
onChange: (newHex) => {
|
||||||
log.info(`Gas price changed to: ${newHex}`)
|
log.info(`Gas price changed to: ${newHex}`)
|
||||||
if (newHex === '0x0') {
|
this.setState({ gasPrice: newHex })
|
||||||
this.setState({gasPrice: gasPriceDefault})
|
|
||||||
} else {
|
|
||||||
this.setState({ gasPrice: newHex })
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
@ -316,7 +306,6 @@ PTXP.gatherParams = function () {
|
|||||||
const state = this.state || {}
|
const state = this.state || {}
|
||||||
const txData = state.txData || props.txData
|
const txData = state.txData || props.txData
|
||||||
const txParams = txData.txParams
|
const txParams = txData.txParams
|
||||||
|
|
||||||
const gas = state.gas || txParams.gas
|
const gas = state.gas || txParams.gas
|
||||||
const gasPrice = state.gasPrice || txParams.gasPrice
|
const gasPrice = state.gasPrice || txParams.gasPrice
|
||||||
const resultTx = extend(txParams, {
|
const resultTx = extend(txParams, {
|
||||||
@ -330,6 +319,16 @@ PTXP.gatherParams = function () {
|
|||||||
return resultTxMeta
|
return resultTxMeta
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PTXP.verifyGasParams = function () {
|
||||||
|
// We call this in case the gas has not been modified at all
|
||||||
|
if (!this.state) { return true }
|
||||||
|
return this._notZeroOrEmptyString(this.state.gas) && this._notZeroOrEmptyString(this.state.gasPrice)
|
||||||
|
}
|
||||||
|
|
||||||
|
PTXP._notZeroOrEmptyString = function (obj) {
|
||||||
|
return obj !== '' && obj !== '0x0'
|
||||||
|
}
|
||||||
|
|
||||||
function forwardCarrat () {
|
function forwardCarrat () {
|
||||||
return (
|
return (
|
||||||
|
|
||||||
|
@ -1,10 +1,18 @@
|
|||||||
const Component = require('react').Component
|
const Component = require('react').Component
|
||||||
|
const connect = require('react-redux').connect
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
const PendingTxDetails = require('./pending-tx-details')
|
const PendingTxDetails = require('./pending-tx-details')
|
||||||
const extend = require('xtend')
|
const extend = require('xtend')
|
||||||
|
const actions = require('../actions')
|
||||||
|
|
||||||
module.exports = PendingTx
|
module.exports = connect(mapStateToProps)(PendingTx)
|
||||||
|
|
||||||
|
function mapStateToProps (state) {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inherits(PendingTx, Component)
|
inherits(PendingTx, Component)
|
||||||
function PendingTx () {
|
function PendingTx () {
|
||||||
@ -60,25 +68,31 @@ PendingTx.prototype.render = function () {
|
|||||||
}, [
|
}, [
|
||||||
|
|
||||||
props.insufficientBalance ?
|
props.insufficientBalance ?
|
||||||
h('button.btn-green', {
|
h('button', {
|
||||||
onClick: props.buyEth,
|
onClick: props.buyEth,
|
||||||
}, 'Buy Ether')
|
}, 'Buy Ether')
|
||||||
: null,
|
: null,
|
||||||
|
|
||||||
h('button.confirm', {
|
|
||||||
disabled: props.insufficientBalance,
|
|
||||||
onClick: props.sendTransaction,
|
|
||||||
}, 'Accept'),
|
|
||||||
|
|
||||||
h('button.cancel.btn-red', {
|
|
||||||
onClick: props.cancelTransaction,
|
|
||||||
}, 'Reject'),
|
|
||||||
|
|
||||||
h('button', {
|
h('button', {
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
this.refs.details.resetGasFields()
|
this.refs.details.resetGasFields()
|
||||||
},
|
},
|
||||||
}, 'Reset'),
|
}, 'Reset'),
|
||||||
|
|
||||||
|
h('button.confirm.btn-green', {
|
||||||
|
disabled: props.insufficientBalance,
|
||||||
|
onClick: (txData, event) => {
|
||||||
|
if (this.refs.details.verifyGasParams()) {
|
||||||
|
props.sendTransaction(txData, event)
|
||||||
|
} else {
|
||||||
|
this.props.dispatch(actions.displayWarning('Invalid Gas Parameters'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}, 'Accept'),
|
||||||
|
|
||||||
|
h('button.cancel.btn-red', {
|
||||||
|
onClick: props.cancelTransaction,
|
||||||
|
}, 'Reject'),
|
||||||
]),
|
]),
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user