aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Serrano <kevgagser@gmail.com>2016-10-20 05:57:30 +0800
committerKevin Serrano <kevgagser@gmail.com>2016-10-20 05:57:30 +0800
commitafbc4c832ba86fcb94b612c93796a5ffa422b457 (patch)
treedbdaa16920fd175171603b182d332dbf87655bd4
parentad3fa24a28c0ec45dca43a257005626a4027487a (diff)
parenta88a48ba14a213920ce1becb0b70cf10192ad3e5 (diff)
downloadtangerine-wallet-browser-afbc4c832ba86fcb94b612c93796a5ffa422b457.tar
tangerine-wallet-browser-afbc4c832ba86fcb94b612c93796a5ffa422b457.tar.gz
tangerine-wallet-browser-afbc4c832ba86fcb94b612c93796a5ffa422b457.tar.bz2
tangerine-wallet-browser-afbc4c832ba86fcb94b612c93796a5ffa422b457.tar.lz
tangerine-wallet-browser-afbc4c832ba86fcb94b612c93796a5ffa422b457.tar.xz
tangerine-wallet-browser-afbc4c832ba86fcb94b612c93796a5ffa422b457.tar.zst
tangerine-wallet-browser-afbc4c832ba86fcb94b612c93796a5ffa422b457.zip
Git merge resolution.
-rw-r--r--CHANGELOG.md11
-rw-r--r--app/manifest.json2
-rw-r--r--app/scripts/contentscript.js16
-rw-r--r--app/scripts/inpage.js2
-rw-r--r--app/scripts/lib/config-manager.js12
-rw-r--r--app/scripts/lib/id-management.js7
-rw-r--r--app/scripts/lib/idStore.js14
-rw-r--r--app/scripts/metamask-controller.js9
-rw-r--r--package.json4
-rw-r--r--test/unit/idStore-test.js18
-rw-r--r--ui/app/actions.js14
-rw-r--r--ui/app/components/pending-tx-details.js2
-rw-r--r--ui/app/components/range-slider.js58
-rw-r--r--ui/app/send.js143
14 files changed, 267 insertions, 45 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8aafb47df..d6d400b66 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,17 @@
## Current Master
+## 2.13.5 2016-10-18
+
+- Increase default max gas to `100000` over the RPC's `estimateGas` response.
+- Fix bug where slow-loading dapps would sometimes trigger infinite reload loops.
+
+## 2.13.4 2016-10-17
+
+- Add custom transaction fee field to send form.
+- Fix bug where web3 was being injected into XML files.
+- Fix bug where changing network would not reload current Dapps.
+
## 2.13.3 2016-10-4
- Fix bug where log queries were filtered out.
diff --git a/app/manifest.json b/app/manifest.json
index badeb7cb2..8f5a34ea6 100644
--- a/app/manifest.json
+++ b/app/manifest.json
@@ -1,7 +1,7 @@
{
"name": "MetaMask",
"short_name": "Metamask",
- "version": "2.13.3",
+ "version": "2.13.5",
"manifest_version": 2,
"author": "https://metamask.io",
"description": "Ethereum Browser Extension",
diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js
index 3ad145e3e..e2a968ac9 100644
--- a/app/scripts/contentscript.js
+++ b/app/scripts/contentscript.js
@@ -69,6 +69,18 @@ function setupStreams(){
}
function shouldInjectWeb3(){
- var shouldInject = (window.location.href.indexOf('.pdf') === -1)
- return shouldInject
+ return isAllowedSuffix(window.location.href)
+}
+
+function isAllowedSuffix(testCase) {
+ var prohibitedTypes = ['xml', 'pdf']
+ var currentUrl = window.location.href
+ var currentRegex
+ for (let i = 0; i < prohibitedTypes.length; i++) {
+ currentRegex = new RegExp(`\.${prohibitedTypes[i]}$`)
+ if (currentRegex.test(currentUrl)) {
+ return false
+ }
+ }
+ return true
}
diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js
index ef199946c..85dd70b4d 100644
--- a/app/scripts/inpage.js
+++ b/app/scripts/inpage.js
@@ -43,7 +43,7 @@ reloadStream.once('data', triggerReload)
var pingChannel = inpageProvider.multiStream.createStream('pingpong')
var pingStream = new PingStream({ objectMode: true })
// wait for first successful reponse
-metamaskStream.once('data', function(){
+metamaskStream.once('_data', function(){
pingStream.pipe(pingChannel).pipe(pingStream)
})
endOfStream(pingStream, triggerReload)
diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js
index 1c0e3b696..d12304c46 100644
--- a/app/scripts/lib/config-manager.js
+++ b/app/scripts/lib/config-manager.js
@@ -416,3 +416,15 @@ ConfigManager.prototype.createShapeShiftTx = function (depositAddress, depositTy
}
this.setData(data)
}
+
+ConfigManager.prototype.getGasMultiplier = function () {
+ var data = this.getData()
+ return ('gasMultiplier' in data) && data.gasMultiplier
+}
+
+ConfigManager.prototype.setGasMultiplier = function (gasMultiplier) {
+ var data = this.getData()
+
+ data.gasMultiplier = gasMultiplier
+ this.setData(data)
+}
diff --git a/app/scripts/lib/id-management.js b/app/scripts/lib/id-management.js
index 2d42e1e30..421f2105f 100644
--- a/app/scripts/lib/id-management.js
+++ b/app/scripts/lib/id-management.js
@@ -7,6 +7,7 @@
*/
const ethUtil = require('ethereumjs-util')
+const BN = ethUtil.BN
const Transaction = require('ethereumjs-tx')
module.exports = IdManagement
@@ -24,7 +25,13 @@ function IdManagement (opts) {
}
this.signTx = function (txParams) {
+ // calculate gas with custom gas multiplier
+ var gasMultiplier = this.configManager.getGasMultiplier() || 1
+ var gasPrice = new BN(ethUtil.stripHexPrefix(txParams.gasPrice), 16)
+ gasPrice = gasPrice.mul(new BN(gasMultiplier * 100, 10)).div(new BN(100, 10))
+ txParams.gasPrice = ethUtil.intToHex(gasPrice.toNumber())
// normalize values
+
txParams.to = ethUtil.addHexPrefix(txParams.to)
txParams.from = ethUtil.addHexPrefix(txParams.from.toLowerCase())
txParams.value = ethUtil.addHexPrefix(txParams.value)
diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js
index 6837a1e8d..9d0ca7f19 100644
--- a/app/scripts/lib/idStore.js
+++ b/app/scripts/lib/idStore.js
@@ -2,6 +2,7 @@ const EventEmitter = require('events').EventEmitter
const inherits = require('util').inherits
const async = require('async')
const ethUtil = require('ethereumjs-util')
+const BN = ethUtil.BN
const EthQuery = require('eth-query')
const KeyStore = require('eth-lightwallet').keystore
const clone = require('clone')
@@ -112,6 +113,8 @@ IdentityStore.prototype.getState = function () {
currentFiat: configManager.getCurrentFiat(),
conversionRate: configManager.getConversionRate(),
conversionDate: configManager.getConversionDate(),
+ gasMultiplier: configManager.getGasMultiplier(),
+
}))
}
@@ -211,6 +214,7 @@ IdentityStore.prototype.exportAccount = function (address, cb) {
// comes from dapp via zero-client hooked-wallet provider
IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDoneCb, cb) {
const configManager = this.configManager
+
var self = this
// create txData obj with parameters and meta data
var time = (new Date()).getTime()
@@ -222,6 +226,7 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone
txParams: txParams,
time: time,
status: 'unconfirmed',
+ gasMultiplier: configManager.getGasMultiplier() || 1,
}
console.log('addUnconfirmedTransaction:', txData)
@@ -262,7 +267,7 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone
function estimateGas(cb){
query.estimateGas(txParams, function(err, result){
if (err) return cb(err)
- txData.estimatedGas = result
+ txData.estimatedGas = self.addGasBuffer(result)
cb()
})
}
@@ -277,6 +282,13 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone
}
}
+IdentityStore.prototype.addGasBuffer = function (gasHex) {
+ var gas = new BN(gasHex, 16)
+ var buffer = new BN('100000', 10)
+ var result = gas.add(buffer)
+ return ethUtil.addHexPrefix(result.toString(16))
+}
+
// comes from metamask ui
IdentityStore.prototype.approveTransaction = function (txId, cb) {
const configManager = this.configManager
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index 9f4fcfefb..92551d633 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -57,6 +57,7 @@ module.exports = class MetamaskController {
agreeToEthWarning: this.agreeToEthWarning.bind(this),
setTOSHash: this.setTOSHash.bind(this),
checkTOSChange: this.checkTOSChange.bind(this),
+ setGasMultiplier: this.setGasMultiplier.bind(this),
// forward directly to idStore
createNewVault: idStore.createNewVault.bind(idStore),
@@ -395,4 +396,12 @@ module.exports = class MetamaskController {
})
}
+ setGasMultiplier (gasMultiplier, cb) {
+ try {
+ this.configManager.setGasMultiplier(gasMultiplier)
+ cb()
+ } catch (e) {
+ cb(e)
+ }
+ }
}
diff --git a/package.json b/package.json
index 53de07e4f..e29ef5185 100644
--- a/package.json
+++ b/package.json
@@ -6,9 +6,9 @@
"scripts": {
"start": "gulp dev",
"lint": "gulp lint",
- "dev": "gulp dev --debug",
- "dist": "gulp dist",
"buildCiUnits": "node test/integration/index.js",
+ "dev": "gulp dev --debug",
+ "dist": "gulp dist --disableLiveReload",
"test": "npm run fastTest && npm run ci && npm run lint",
"fastTest": "mocha --require test/helper.js --compilers js:babel-register --recursive \"test/unit/**/*.js\"",
"watch": "mocha watch --compilers js:babel-register --recursive \"test/unit/**/*.js\"",
diff --git a/test/unit/idStore-test.js b/test/unit/idStore-test.js
index 31da2cd3d..0a57d2121 100644
--- a/test/unit/idStore-test.js
+++ b/test/unit/idStore-test.js
@@ -2,6 +2,7 @@ var assert = require('assert')
var IdentityStore = require('../../app/scripts/lib/idStore')
var configManagerGen = require('../lib/mock-config-manager')
const ethUtil = require('ethereumjs-util')
+const BN = ethUtil.BN
const async = require('async')
describe('IdentityStore', function() {
@@ -138,4 +139,21 @@ describe('IdentityStore', function() {
})
})
})
+
+ describe('#addGasBuffer', function() {
+ const idStore = new IdentityStore({
+ configManager: configManagerGen(),
+ ethStore: {
+ addAccount(acct) { accounts.push(ethUtil.addHexPrefix(acct)) },
+ },
+ })
+
+ const gas = '0x01'
+ const bnGas = new BN(gas, 16)
+ const result = idStore.addGasBuffer(gas)
+ const bnResult = new BN(result, 16)
+
+ assert.ok(bnResult.gt(gas), 'added more gas as buffer.')
+ assert.equal(result.indexOf('0x'), 0, 'include hex prefix')
+ })
})
diff --git a/ui/app/actions.js b/ui/app/actions.js
index a594fa321..a6601cd0e 100644
--- a/ui/app/actions.js
+++ b/ui/app/actions.js
@@ -225,14 +225,16 @@ function signMsg (msgData) {
function signTx (txData) {
return (dispatch) => {
- web3.eth.sendTransaction(txData, (err, data) => {
- dispatch(actions.hideLoadingIndication())
-
+ _accountManager.setGasMultiplier(txData.gasMultiplier, (err) => {
if (err) return dispatch(actions.displayWarning(err.message))
- dispatch(actions.hideWarning())
- dispatch(actions.goHome())
+ web3.eth.sendTransaction(txData, (err, data) => {
+ dispatch(actions.hideLoadingIndication())
+ if (err) return dispatch(actions.displayWarning(err.message))
+ dispatch(actions.hideWarning())
+ dispatch(actions.goHome())
+ })
+ dispatch(this.showConfTxPage())
})
- dispatch(this.showConfTxPage())
}
}
diff --git a/ui/app/components/pending-tx-details.js b/ui/app/components/pending-tx-details.js
index d8e8524bf..545302098 100644
--- a/ui/app/components/pending-tx-details.js
+++ b/ui/app/components/pending-tx-details.js
@@ -29,8 +29,10 @@ PTXP.render = function () {
var account = props.accounts[address]
var balance = account ? account.balance : '0x0'
+ var gasMultiplier = txData.gasMultiplier
var gasCost = new BN(ethUtil.stripHexPrefix(txParams.gas || txData.estimatedGas), 16)
var gasPrice = new BN(ethUtil.stripHexPrefix(txParams.gasPrice || '0x4a817c800'), 16)
+ gasPrice = gasPrice.mul(new BN(gasMultiplier * 100), 10).div(new BN(100, 10))
var txFee = gasCost.mul(gasPrice)
var txValue = new BN(ethUtil.stripHexPrefix(txParams.value || '0x0'), 16)
var maxCost = txValue.add(txFee)
diff --git a/ui/app/components/range-slider.js b/ui/app/components/range-slider.js
new file mode 100644
index 000000000..823f5eb01
--- /dev/null
+++ b/ui/app/components/range-slider.js
@@ -0,0 +1,58 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+
+module.exports = RangeSlider
+
+inherits(RangeSlider, Component)
+function RangeSlider () {
+ Component.call(this)
+}
+
+RangeSlider.prototype.render = function () {
+ const state = this.state || {}
+ const props = this.props
+ const onInput = props.onInput || function () {}
+ const name = props.name
+ const {
+ min = 0,
+ max = 100,
+ increment = 1,
+ defaultValue = 50,
+ mirrorInput = false,
+ } = this.props.options
+ const {container, input, range} = props.style
+
+ return (
+ h('.flex-row', {
+ style: container,
+ }, [
+ h('input', {
+ type: 'range',
+ name: name,
+ min: min,
+ max: max,
+ step: increment,
+ style: range,
+ value: state.value || defaultValue,
+ onChange: mirrorInput ? this.mirrorInputs.bind(this, event) : onInput,
+ }),
+
+ // Mirrored input for range
+ mirrorInput ? h('input.large-input', {
+ type: 'number',
+ name: `${name}Mirror`,
+ min: min,
+ max: max,
+ value: state.value || defaultValue,
+ step: increment,
+ style: input,
+ onChange: this.mirrorInputs.bind(this, event),
+ }) : null,
+ ])
+ )
+}
+
+RangeSlider.prototype.mirrorInputs = function (event) {
+ this.setState({value: event.target.value})
+}
diff --git a/ui/app/send.js b/ui/app/send.js
index 009866cf7..97ed29e4a 100644
--- a/ui/app/send.js
+++ b/ui/app/send.js
@@ -9,7 +9,8 @@ const numericBalance = require('./util').numericBalance
const addressSummary = require('./util').addressSummary
const EthBalance = require('./components/eth-balance')
const ethUtil = require('ethereumjs-util')
-
+const RangeSlider = require('./components/range-slider')
+const Tooltip = require('./components/tooltip')
module.exports = connect(mapStateToProps)(SendTransactionScreen)
function mapStateToProps (state) {
@@ -50,7 +51,7 @@ SendTransactionScreen.prototype.render = function () {
// Sender Profile
//
- h('.account-data-subsection.flex-column.flex-grow', {
+ h('.account-data-subsection.flex-row.flex-grow', {
style: {
margin: '0 20px',
},
@@ -59,10 +60,9 @@ SendTransactionScreen.prototype.render = function () {
// header - identicon + nav
h('.flex-row.flex-space-between', {
style: {
- marginTop: 28,
+ marginTop: '15px',
},
}, [
-
// back button
h('i.fa.fa-arrow-left.fa-lg.cursor-pointer.color-orange', {
onClick: this.back.bind(this),
@@ -77,42 +77,53 @@ SendTransactionScreen.prototype.render = function () {
]),
// invisible place holder
- h('i.fa.fa-users.fa-lg.invisible'),
+ h('i.fa.fa-users.fa-lg.invisible', {
+ style: {
+ marginTop: '28px',
+ },
+ }),
]),
// account label
- h('h2.font-medium.color-forest.flex-center', {
- style: {
- paddingTop: 8,
- marginBottom: 8,
- },
- }, identity && identity.name),
- // address and getter actions
- h('.flex-row.flex-center', {
+ h('.flex-column', {
style: {
- marginBottom: 8,
+ marginTop: '10px',
+ alignItems: 'flex-start',
},
}, [
+ h('h2.font-medium.color-forest.flex-center', {
+ style: {
+ paddingTop: '8px',
+ marginBottom: '8px',
+ },
+ }, identity && identity.name),
- h('div', {
+ // address and getter actions
+ h('.flex-row.flex-center', {
style: {
- lineHeight: '16px',
+ marginBottom: '8px',
},
- }, addressSummary(address)),
+ }, [
- ]),
+ h('div', {
+ style: {
+ lineHeight: '16px',
+ },
+ }, addressSummary(address)),
- // balance
- h('.flex-row.flex-center', [
+ ]),
- h(EthBalance, {
- value: account && account.balance,
- }),
+ // balance
+ h('.flex-row.flex-center', [
- ]),
+ h(EthBalance, {
+ value: account && account.balance,
+ }),
+ ]),
+ ]),
]),
//
@@ -123,8 +134,8 @@ SendTransactionScreen.prototype.render = function () {
style: {
background: '#EBEBEB',
color: '#AEAEAE',
- marginTop: 32,
- marginBottom: 16,
+ marginTop: '15px',
+ marginBottom: '16px',
},
}, [
'Send Transaction',
@@ -152,7 +163,7 @@ SendTransactionScreen.prototype.render = function () {
placeholder: 'Amount',
type: 'number',
style: {
- marginRight: 6,
+ marginRight: '6px',
},
dataset: {
persistentFormId: 'tx-amount',
@@ -171,20 +182,19 @@ SendTransactionScreen.prototype.render = function () {
//
// Optional Fields
//
-
h('h3.flex-center.text-transform-uppercase', {
style: {
background: '#EBEBEB',
color: '#AEAEAE',
- marginTop: 16,
- marginBottom: 16,
+ marginTop: '16px',
+ marginBottom: '16px',
},
}, [
'Transactional Data (optional)',
]),
// 'data' field
- h('section.flex-row.flex-center', [
+ h('section.flex-column.flex-center', [
h('input.large-input', {
name: 'txData',
placeholder: '0x01234',
@@ -197,6 +207,73 @@ SendTransactionScreen.prototype.render = function () {
},
}),
]),
+ // custom gasPrice field
+ h('h3.flex-center.text-transform-uppercase', {
+ style: {
+ background: '#EBEBEB',
+ color: '#AEAEAE',
+ marginBottom: '5px',
+ },
+ }, [
+ 'Transaction Fee (optional)',
+ h(Tooltip, {
+ title: `
+ This is used to set the transaction's gas price.
+ Setting it to 100% will use the full recommended value. `,
+ }, [
+ h('i.fa.fa-question-circle', {
+ style: {
+ marginLeft: '5px',
+ },
+ }),
+ ]),
+ ]),
+
+ h('section.flex-column.flex-center', [
+ h('.flex-row', [
+ h(RangeSlider, {
+ name: 'gasInput',
+ options: {
+ mirrorInput: true,
+ defaultValue: 100,
+ min: 80,
+ max: 220,
+ },
+ style: {
+ container: {
+ marginBottom: '16px',
+ },
+ range: {
+ width: '68vw',
+ },
+ input: {
+ width: '5em',
+ marginLeft: '5px',
+ },
+ },
+ }),
+
+ h('div', {
+ style: {
+ fontSize: '12px',
+ paddingTop: '8px',
+ paddingLeft: '5px',
+ },
+ }, '%'),
+ ]),
+ h('.flex-row', {
+ style: {
+ justifyContent: 'space-between',
+ width: '243px',
+ position: 'relative',
+ fontSize: '12px',
+ right: '42px',
+ bottom: '30px',
+ },
+ }, [
+ h('span', 'Cheaper'), h('span', 'Faster'),
+ ]),
+ ]),
])
)
}
@@ -211,11 +288,12 @@ SendTransactionScreen.prototype.back = function () {
this.props.dispatch(actions.backToAccountDetail(address))
}
-SendTransactionScreen.prototype.onSubmit = function () {
+SendTransactionScreen.prototype.onSubmit = function (gasPrice) {
const recipient = document.querySelector('input[name="address"]').value
const input = document.querySelector('input[name="amount"]').value
const value = util.normalizeEthStringToWei(input)
const txData = document.querySelector('input[name="txData"]').value
+ const gasMultiplier = document.querySelector('input[name="gasInput"]').value
const balance = this.props.balance
let message
@@ -239,6 +317,7 @@ SendTransactionScreen.prototype.onSubmit = function () {
var txParams = {
from: this.props.address,
value: '0x' + value.toString(16),
+ gasMultiplier: gasMultiplier * 0.01,
}
if (recipient) txParams.to = ethUtil.addHexPrefix(recipient)