mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 18:00:18 +01:00
Merge pull request #720 from MetaMask/i#495CustomGasField
add a gasPrice field
This commit is contained in:
commit
11c114599c
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
## Current Master
|
## Current Master
|
||||||
|
|
||||||
|
- Add a custom transaction fee field to send form.
|
||||||
|
|
||||||
## 2.13.3 2016-10-4
|
## 2.13.3 2016-10-4
|
||||||
|
|
||||||
- Fix bug where log queries were filtered out.
|
- Fix bug where log queries were filtered out.
|
||||||
|
@ -384,3 +384,15 @@ ConfigManager.prototype.createShapeShiftTx = function (depositAddress, depositTy
|
|||||||
}
|
}
|
||||||
this.setData(data)
|
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)
|
||||||
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
|
const BN = ethUtil.BN
|
||||||
const Transaction = require('ethereumjs-tx')
|
const Transaction = require('ethereumjs-tx')
|
||||||
|
|
||||||
module.exports = IdManagement
|
module.exports = IdManagement
|
||||||
@ -24,7 +25,13 @@ function IdManagement (opts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.signTx = function (txParams) {
|
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
|
// normalize values
|
||||||
|
|
||||||
txParams.to = ethUtil.addHexPrefix(txParams.to)
|
txParams.to = ethUtil.addHexPrefix(txParams.to)
|
||||||
txParams.from = ethUtil.addHexPrefix(txParams.from.toLowerCase())
|
txParams.from = ethUtil.addHexPrefix(txParams.from.toLowerCase())
|
||||||
txParams.value = ethUtil.addHexPrefix(txParams.value)
|
txParams.value = ethUtil.addHexPrefix(txParams.value)
|
||||||
|
@ -112,6 +112,8 @@ IdentityStore.prototype.getState = function () {
|
|||||||
currentFiat: configManager.getCurrentFiat(),
|
currentFiat: configManager.getCurrentFiat(),
|
||||||
conversionRate: configManager.getConversionRate(),
|
conversionRate: configManager.getConversionRate(),
|
||||||
conversionDate: configManager.getConversionDate(),
|
conversionDate: configManager.getConversionDate(),
|
||||||
|
gasMultiplier: configManager.getGasMultiplier(),
|
||||||
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,6 +213,7 @@ IdentityStore.prototype.exportAccount = function (address, cb) {
|
|||||||
// comes from dapp via zero-client hooked-wallet provider
|
// comes from dapp via zero-client hooked-wallet provider
|
||||||
IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDoneCb, cb) {
|
IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDoneCb, cb) {
|
||||||
const configManager = this.configManager
|
const configManager = this.configManager
|
||||||
|
|
||||||
var self = this
|
var self = this
|
||||||
// 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()
|
||||||
@ -222,6 +225,7 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone
|
|||||||
txParams: txParams,
|
txParams: txParams,
|
||||||
time: time,
|
time: time,
|
||||||
status: 'unconfirmed',
|
status: 'unconfirmed',
|
||||||
|
gasMultiplier: configManager.getGasMultiplier() || 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('addUnconfirmedTransaction:', txData)
|
console.log('addUnconfirmedTransaction:', txData)
|
||||||
|
@ -55,6 +55,7 @@ module.exports = class MetamaskController {
|
|||||||
agreeToEthWarning: this.agreeToEthWarning.bind(this),
|
agreeToEthWarning: this.agreeToEthWarning.bind(this),
|
||||||
setTOSHash: this.setTOSHash.bind(this),
|
setTOSHash: this.setTOSHash.bind(this),
|
||||||
checkTOSChange: this.checkTOSChange.bind(this),
|
checkTOSChange: this.checkTOSChange.bind(this),
|
||||||
|
setGasMultiplier: this.setGasMultiplier.bind(this),
|
||||||
|
|
||||||
// forward directly to idStore
|
// forward directly to idStore
|
||||||
createNewVault: idStore.createNewVault.bind(idStore),
|
createNewVault: idStore.createNewVault.bind(idStore),
|
||||||
@ -377,4 +378,13 @@ module.exports = class MetamaskController {
|
|||||||
createShapeShiftTx (depositAddress, depositType) {
|
createShapeShiftTx (depositAddress, depositType) {
|
||||||
this.configManager.createShapeShiftTx(depositAddress, depositType)
|
this.configManager.createShapeShiftTx(depositAddress, depositType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setGasMultiplier (gasMultiplier, cb) {
|
||||||
|
try {
|
||||||
|
this.configManager.setGasMultiplier(gasMultiplier)
|
||||||
|
cb()
|
||||||
|
} catch (e) {
|
||||||
|
cb(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -278,14 +278,16 @@ function signMsg (msgData) {
|
|||||||
|
|
||||||
function signTx (txData) {
|
function signTx (txData) {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
web3.eth.sendTransaction(txData, (err, data) => {
|
_accountManager.setGasMultiplier(txData.gasMultiplier, (err) => {
|
||||||
dispatch(actions.hideLoadingIndication())
|
|
||||||
|
|
||||||
if (err) return dispatch(actions.displayWarning(err.message))
|
if (err) return dispatch(actions.displayWarning(err.message))
|
||||||
dispatch(actions.hideWarning())
|
web3.eth.sendTransaction(txData, (err, data) => {
|
||||||
dispatch(actions.goHome())
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
if (err) return dispatch(actions.displayWarning(err.message))
|
||||||
|
dispatch(actions.hideWarning())
|
||||||
|
dispatch(actions.goHome())
|
||||||
|
})
|
||||||
|
dispatch(this.showConfTxPage())
|
||||||
})
|
})
|
||||||
dispatch(this.showConfTxPage())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,8 +29,10 @@ 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'
|
||||||
|
|
||||||
|
var gasMultiplier = txData.gasMultiplier
|
||||||
var gasCost = new BN(ethUtil.stripHexPrefix(txParams.gas || txData.estimatedGas), 16)
|
var gasCost = new BN(ethUtil.stripHexPrefix(txParams.gas || txData.estimatedGas), 16)
|
||||||
var gasPrice = new BN(ethUtil.stripHexPrefix(txParams.gasPrice || '0x4a817c800'), 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 txFee = gasCost.mul(gasPrice)
|
||||||
var txValue = new BN(ethUtil.stripHexPrefix(txParams.value || '0x0'), 16)
|
var txValue = new BN(ethUtil.stripHexPrefix(txParams.value || '0x0'), 16)
|
||||||
var maxCost = txValue.add(txFee)
|
var maxCost = txValue.add(txFee)
|
||||||
|
58
ui/app/components/range-slider.js
Normal file
58
ui/app/components/range-slider.js
Normal file
@ -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})
|
||||||
|
}
|
163
ui/app/send.js
163
ui/app/send.js
@ -9,7 +9,8 @@ const numericBalance = require('./util').numericBalance
|
|||||||
const addressSummary = require('./util').addressSummary
|
const addressSummary = require('./util').addressSummary
|
||||||
const EthBalance = require('./components/eth-balance')
|
const EthBalance = require('./components/eth-balance')
|
||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
|
const RangeSlider = require('./components/range-slider')
|
||||||
|
const Tooltip = require('./components/tooltip')
|
||||||
module.exports = connect(mapStateToProps)(SendTransactionScreen)
|
module.exports = connect(mapStateToProps)(SendTransactionScreen)
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
@ -50,7 +51,7 @@ SendTransactionScreen.prototype.render = function () {
|
|||||||
// Sender Profile
|
// Sender Profile
|
||||||
//
|
//
|
||||||
|
|
||||||
h('.account-data-subsection.flex-column.flex-grow', {
|
h('.account-data-subsection.flex-row.flex-grow', {
|
||||||
style: {
|
style: {
|
||||||
margin: '0 20px',
|
margin: '0 20px',
|
||||||
},
|
},
|
||||||
@ -59,10 +60,9 @@ SendTransactionScreen.prototype.render = function () {
|
|||||||
// header - identicon + nav
|
// header - identicon + nav
|
||||||
h('.flex-row.flex-space-between', {
|
h('.flex-row.flex-space-between', {
|
||||||
style: {
|
style: {
|
||||||
marginTop: 28,
|
marginTop: '15px',
|
||||||
},
|
},
|
||||||
}, [
|
}, [
|
||||||
|
|
||||||
// back button
|
// back button
|
||||||
h('i.fa.fa-arrow-left.fa-lg.cursor-pointer.color-orange', {
|
h('i.fa.fa-arrow-left.fa-lg.cursor-pointer.color-orange', {
|
||||||
onClick: this.back.bind(this),
|
onClick: this.back.bind(this),
|
||||||
@ -77,42 +77,53 @@ SendTransactionScreen.prototype.render = function () {
|
|||||||
]),
|
]),
|
||||||
|
|
||||||
// invisible place holder
|
// invisible place holder
|
||||||
h('i.fa.fa-users.fa-lg.invisible'),
|
h('i.fa.fa-users.fa-lg.invisible', {
|
||||||
|
|
||||||
]),
|
|
||||||
|
|
||||||
// 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', {
|
|
||||||
style: {
|
|
||||||
marginBottom: 8,
|
|
||||||
},
|
|
||||||
}, [
|
|
||||||
|
|
||||||
h('div', {
|
|
||||||
style: {
|
style: {
|
||||||
lineHeight: '16px',
|
marginTop: '28px',
|
||||||
},
|
},
|
||||||
}, addressSummary(address)),
|
|
||||||
|
|
||||||
]),
|
|
||||||
|
|
||||||
// balance
|
|
||||||
h('.flex-row.flex-center', [
|
|
||||||
|
|
||||||
h(EthBalance, {
|
|
||||||
value: account && account.balance,
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
]),
|
]),
|
||||||
|
|
||||||
|
// account label
|
||||||
|
|
||||||
|
h('.flex-column', {
|
||||||
|
style: {
|
||||||
|
marginTop: '10px',
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('h2.font-medium.color-forest.flex-center', {
|
||||||
|
style: {
|
||||||
|
paddingTop: '8px',
|
||||||
|
marginBottom: '8px',
|
||||||
|
},
|
||||||
|
}, identity && identity.name),
|
||||||
|
|
||||||
|
// address and getter actions
|
||||||
|
h('.flex-row.flex-center', {
|
||||||
|
style: {
|
||||||
|
marginBottom: '8px',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
|
||||||
|
h('div', {
|
||||||
|
style: {
|
||||||
|
lineHeight: '16px',
|
||||||
|
},
|
||||||
|
}, addressSummary(address)),
|
||||||
|
|
||||||
|
]),
|
||||||
|
|
||||||
|
// balance
|
||||||
|
h('.flex-row.flex-center', [
|
||||||
|
|
||||||
|
h(EthBalance, {
|
||||||
|
value: account && account.balance,
|
||||||
|
}),
|
||||||
|
|
||||||
|
]),
|
||||||
|
]),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -123,8 +134,8 @@ SendTransactionScreen.prototype.render = function () {
|
|||||||
style: {
|
style: {
|
||||||
background: '#EBEBEB',
|
background: '#EBEBEB',
|
||||||
color: '#AEAEAE',
|
color: '#AEAEAE',
|
||||||
marginTop: 32,
|
marginTop: '15px',
|
||||||
marginBottom: 16,
|
marginBottom: '16px',
|
||||||
},
|
},
|
||||||
}, [
|
}, [
|
||||||
'Send Transaction',
|
'Send Transaction',
|
||||||
@ -152,7 +163,7 @@ SendTransactionScreen.prototype.render = function () {
|
|||||||
placeholder: 'Amount',
|
placeholder: 'Amount',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
style: {
|
style: {
|
||||||
marginRight: 6,
|
marginRight: '6px',
|
||||||
},
|
},
|
||||||
dataset: {
|
dataset: {
|
||||||
persistentFormId: 'tx-amount',
|
persistentFormId: 'tx-amount',
|
||||||
@ -171,20 +182,19 @@ SendTransactionScreen.prototype.render = function () {
|
|||||||
//
|
//
|
||||||
// Optional Fields
|
// Optional Fields
|
||||||
//
|
//
|
||||||
|
|
||||||
h('h3.flex-center.text-transform-uppercase', {
|
h('h3.flex-center.text-transform-uppercase', {
|
||||||
style: {
|
style: {
|
||||||
background: '#EBEBEB',
|
background: '#EBEBEB',
|
||||||
color: '#AEAEAE',
|
color: '#AEAEAE',
|
||||||
marginTop: 16,
|
marginTop: '16px',
|
||||||
marginBottom: 16,
|
marginBottom: '16px',
|
||||||
},
|
},
|
||||||
}, [
|
}, [
|
||||||
'Transactional Data (optional)',
|
'Transactional Data (optional)',
|
||||||
]),
|
]),
|
||||||
|
|
||||||
// 'data' field
|
// 'data' field
|
||||||
h('section.flex-row.flex-center', [
|
h('section.flex-column.flex-center', [
|
||||||
h('input.large-input', {
|
h('input.large-input', {
|
||||||
name: 'txData',
|
name: 'txData',
|
||||||
placeholder: '0x01234',
|
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))
|
this.props.dispatch(actions.backToAccountDetail(address))
|
||||||
}
|
}
|
||||||
|
|
||||||
SendTransactionScreen.prototype.onSubmit = function () {
|
SendTransactionScreen.prototype.onSubmit = function (gasPrice) {
|
||||||
const recipient = document.querySelector('input[name="address"]').value
|
const recipient = document.querySelector('input[name="address"]').value
|
||||||
const input = document.querySelector('input[name="amount"]').value
|
const input = document.querySelector('input[name="amount"]').value
|
||||||
const value = util.normalizeEthStringToWei(input)
|
const value = util.normalizeEthStringToWei(input)
|
||||||
const txData = document.querySelector('input[name="txData"]').value
|
const txData = document.querySelector('input[name="txData"]').value
|
||||||
|
const gasMultiplier = document.querySelector('input[name="gasInput"]').value
|
||||||
const balance = this.props.balance
|
const balance = this.props.balance
|
||||||
let message
|
let message
|
||||||
|
|
||||||
@ -239,6 +317,7 @@ SendTransactionScreen.prototype.onSubmit = function () {
|
|||||||
var txParams = {
|
var txParams = {
|
||||||
from: this.props.address,
|
from: this.props.address,
|
||||||
value: '0x' + value.toString(16),
|
value: '0x' + value.toString(16),
|
||||||
|
gasMultiplier: gasMultiplier * 0.01,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recipient) txParams.to = ethUtil.addHexPrefix(recipient)
|
if (recipient) txParams.to = ethUtil.addHexPrefix(recipient)
|
||||||
|
Loading…
Reference in New Issue
Block a user