mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 01:39:44 +01:00
Merge pull request #673 from MetaMask/i#519buyButtonTxConf
Drop the buy button in if tx is more then account balance
This commit is contained in:
commit
a5e45820cc
@ -127,14 +127,14 @@
|
|||||||
"no-whitespace-before-property": 2,
|
"no-whitespace-before-property": 2,
|
||||||
"no-with": 2,
|
"no-with": 2,
|
||||||
"one-var": [2, { "initialized": "never" }],
|
"one-var": [2, { "initialized": "never" }],
|
||||||
"operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }],
|
"operator-linebreak": [1, "after", { "overrides": { "?": "before", ":": "before" } }],
|
||||||
"padded-blocks": [1, "never"],
|
"padded-blocks": [1, "never"],
|
||||||
"quotes": [2, "single", "avoid-escape"],
|
"quotes": [2, "single", "avoid-escape"],
|
||||||
"semi": [2, "never"],
|
"semi": [2, "never"],
|
||||||
"semi-spacing": [2, { "before": false, "after": true }],
|
"semi-spacing": [2, { "before": false, "after": true }],
|
||||||
"space-before-blocks": [1, "always"],
|
"space-before-blocks": [1, "always"],
|
||||||
"space-before-function-paren": [1, "always"],
|
"space-before-function-paren": [1, "always"],
|
||||||
"space-in-parens": [2, "never"],
|
"space-in-parens": [1, "never"],
|
||||||
"space-infix-ops": 2,
|
"space-infix-ops": 2,
|
||||||
"space-unary-ops": [2, { "words": true, "nonwords": false }],
|
"space-unary-ops": [2, { "words": true, "nonwords": false }],
|
||||||
"spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","] }],
|
"spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","] }],
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## Current Master
|
## Current Master
|
||||||
|
- Show "Buy Ether" button and warning on tx confirmation when sender balance is insufficient
|
||||||
|
|
||||||
## 2.12.1 2016-09-14
|
## 2.12.1 2016-09-14
|
||||||
|
|
||||||
|
@ -334,7 +334,7 @@ module.exports = class MetamaskController {
|
|||||||
var url = `https://buy.coinbase.com/?code=9ec56d01-7e81-5017-930c-513daa27bb6a&amount=${amount}&address=${address}&crypto_currency=ETH`
|
var url = `https://buy.coinbase.com/?code=9ec56d01-7e81-5017-930c-513daa27bb6a&amount=${amount}&address=${address}&crypto_currency=ETH`
|
||||||
|
|
||||||
if (network === '2') {
|
if (network === '2') {
|
||||||
url = 'https://testfaucet.metamask.io/'
|
url = 'https://faucet.metamask.io/'
|
||||||
}
|
}
|
||||||
|
|
||||||
extension.tabs.create({
|
extension.tabs.create({
|
||||||
|
@ -279,10 +279,11 @@ AccountDetailScreen.prototype.requestAccountExport = function () {
|
|||||||
|
|
||||||
AccountDetailScreen.prototype.buyButtonDeligator = function () {
|
AccountDetailScreen.prototype.buyButtonDeligator = function () {
|
||||||
var props = this.props
|
var props = this.props
|
||||||
|
var selected = props.address || Object.keys(props.accounts)[0]
|
||||||
|
|
||||||
if (this.props.accountDetail.subview === 'buyForm') {
|
if (this.props.accountDetail.subview === 'buyForm') {
|
||||||
props.dispatch(actions.backToAccountDetail(props.address))
|
props.dispatch(actions.backToAccountDetail(props.address))
|
||||||
} else {
|
} else {
|
||||||
props.dispatch(actions.buyEthView())
|
props.dispatch(actions.buyEthView(selected))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -479,9 +479,10 @@ function showAccountsPage () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showConfTxPage () {
|
function showConfTxPage (transForward = true) {
|
||||||
return {
|
return {
|
||||||
type: actions.SHOW_CONF_TX_PAGE,
|
type: actions.SHOW_CONF_TX_PAGE,
|
||||||
|
transForward: transForward,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ function mapStateToProps (state) {
|
|||||||
buyView: state.appState.buyView,
|
buyView: state.appState.buyView,
|
||||||
network: state.metamask.network,
|
network: state.metamask.network,
|
||||||
provider: state.metamask.provider,
|
provider: state.metamask.provider,
|
||||||
|
context: state.appState.currentView.context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +39,7 @@ BuyButtonSubview.prototype.render = function () {
|
|||||||
},
|
},
|
||||||
}, [
|
}, [
|
||||||
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: () => props.dispatch(actions.backToAccountDetail(props.selectedAccount)),
|
onClick: this.backButtonContext.bind(this),
|
||||||
style: {
|
style: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
left: '10px',
|
left: '10px',
|
||||||
@ -121,3 +122,11 @@ BuyButtonSubview.prototype.formVersionSubview = function () {
|
|||||||
BuyButtonSubview.prototype.navigateTo = function (url) {
|
BuyButtonSubview.prototype.navigateTo = function (url) {
|
||||||
extension.tabs.create({ url })
|
extension.tabs.create({ url })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BuyButtonSubview.prototype.backButtonContext = function () {
|
||||||
|
if (this.props.context === 'confTx') {
|
||||||
|
this.props.dispatch(actions.showConfTxPage(false))
|
||||||
|
} else {
|
||||||
|
this.props.dispatch(actions.goHome())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,12 +4,12 @@ const inherits = require('util').inherits
|
|||||||
|
|
||||||
const MiniAccountPanel = require('./mini-account-panel')
|
const MiniAccountPanel = require('./mini-account-panel')
|
||||||
const EthBalance = require('./eth-balance')
|
const EthBalance = require('./eth-balance')
|
||||||
const addressSummary = require('../util').addressSummary
|
const util = require('../util')
|
||||||
|
const addressSummary = util.addressSummary
|
||||||
const nameForAddress = require('../../lib/contract-namer')
|
const nameForAddress = require('../../lib/contract-namer')
|
||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
const BN = ethUtil.BN
|
const BN = ethUtil.BN
|
||||||
|
|
||||||
|
|
||||||
module.exports = PendingTxDetails
|
module.exports = PendingTxDetails
|
||||||
|
|
||||||
inherits(PendingTxDetails, Component)
|
inherits(PendingTxDetails, Component)
|
||||||
|
@ -3,7 +3,6 @@ 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')
|
||||||
|
|
||||||
|
|
||||||
module.exports = PendingTx
|
module.exports = PendingTx
|
||||||
|
|
||||||
inherits(PendingTx, Component)
|
inherits(PendingTx, Component)
|
||||||
@ -31,6 +30,15 @@ PendingTx.prototype.render = function () {
|
|||||||
}
|
}
|
||||||
`),
|
`),
|
||||||
|
|
||||||
|
state.insufficientBalance ?
|
||||||
|
h('span.error', {
|
||||||
|
style: {
|
||||||
|
marginLeft: 50,
|
||||||
|
fontSize: '0.9em',
|
||||||
|
},
|
||||||
|
}, 'Insufficient balance for transaction')
|
||||||
|
: null,
|
||||||
|
|
||||||
// send + cancel
|
// send + cancel
|
||||||
h('.flex-row.flex-space-around.conf-buttons', {
|
h('.flex-row.flex-space-around.conf-buttons', {
|
||||||
style: {
|
style: {
|
||||||
@ -39,17 +47,22 @@ PendingTx.prototype.render = function () {
|
|||||||
margin: '14px 25px',
|
margin: '14px 25px',
|
||||||
},
|
},
|
||||||
}, [
|
}, [
|
||||||
|
|
||||||
|
state.insufficientBalance ?
|
||||||
|
h('button.btn-green', {
|
||||||
|
onClick: state.buyEth,
|
||||||
|
}, 'Buy Ether')
|
||||||
|
: null,
|
||||||
|
|
||||||
h('button.confirm', {
|
h('button.confirm', {
|
||||||
|
disabled: state.insufficientBalance,
|
||||||
onClick: state.sendTransaction,
|
onClick: state.sendTransaction,
|
||||||
style: { background: 'rgb(251,117,1)' },
|
|
||||||
}, 'Accept'),
|
}, 'Accept'),
|
||||||
|
|
||||||
h('button.cancel', {
|
h('button.cancel.btn-red', {
|
||||||
onClick: state.cancelTransaction,
|
onClick: state.cancelTransaction,
|
||||||
style: { background: 'rgb(254,35,17)' },
|
|
||||||
}, 'Reject'),
|
}, 'Reject'),
|
||||||
]),
|
]),
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@ const connect = require('react-redux').connect
|
|||||||
const actions = require('./actions')
|
const actions = require('./actions')
|
||||||
const txHelper = require('../lib/tx-helper')
|
const txHelper = require('../lib/tx-helper')
|
||||||
const isPopupOrNotification = require('../../app/scripts/lib/is-popup-or-notification')
|
const isPopupOrNotification = require('../../app/scripts/lib/is-popup-or-notification')
|
||||||
|
const ethUtil = require('ethereumjs-util')
|
||||||
|
const BN = ethUtil.BN
|
||||||
|
|
||||||
const PendingTx = require('./components/pending-tx')
|
const PendingTx = require('./components/pending-tx')
|
||||||
const PendingMsg = require('./components/pending-msg')
|
const PendingMsg = require('./components/pending-msg')
|
||||||
@ -39,6 +41,7 @@ ConfirmTxScreen.prototype.render = function () {
|
|||||||
var unconfTxList = txHelper(unconfTxs, unconfMsgs, network)
|
var unconfTxList = txHelper(unconfTxs, unconfMsgs, network)
|
||||||
var index = state.index !== undefined ? state.index : 0
|
var index = state.index !== undefined ? state.index : 0
|
||||||
var txData = unconfTxList[index] || unconfTxList[0] || {}
|
var txData = unconfTxList[index] || unconfTxList[0] || {}
|
||||||
|
var txParams = txData.txParams || {}
|
||||||
var isNotification = isPopupOrNotification() === 'notification'
|
var isNotification = isPopupOrNotification() === 'notification'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -90,7 +93,9 @@ ConfirmTxScreen.prototype.render = function () {
|
|||||||
selectedAddress: state.selectedAddress,
|
selectedAddress: state.selectedAddress,
|
||||||
accounts: state.accounts,
|
accounts: state.accounts,
|
||||||
identities: state.identities,
|
identities: state.identities,
|
||||||
|
insufficientBalance: this.checkBalnceAgainstTx(txData),
|
||||||
// Actions
|
// Actions
|
||||||
|
buyEth: this.buyEth.bind(this, txParams.from || state.selectedAddress),
|
||||||
sendTransaction: this.sendTransaction.bind(this, txData),
|
sendTransaction: this.sendTransaction.bind(this, txData),
|
||||||
cancelTransaction: this.cancelTransaction.bind(this, txData),
|
cancelTransaction: this.cancelTransaction.bind(this, txData),
|
||||||
signMessage: this.signMessage.bind(this, txData),
|
signMessage: this.signMessage.bind(this, txData),
|
||||||
@ -111,6 +116,28 @@ function currentTxView (opts) {
|
|||||||
return h(PendingMsg, opts)
|
return h(PendingMsg, opts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ConfirmTxScreen.prototype.checkBalnceAgainstTx = function (txData) {
|
||||||
|
var state = this.props
|
||||||
|
|
||||||
|
var txParams = txData.txParams || {}
|
||||||
|
var address = txParams.from || state.selectedAddress
|
||||||
|
var account = state.accounts[address]
|
||||||
|
var balance = account ? account.balance : '0x0'
|
||||||
|
|
||||||
|
var gasCost = new BN(ethUtil.stripHexPrefix(txParams.gas || txData.estimatedGas), 16)
|
||||||
|
var gasPrice = new BN(ethUtil.stripHexPrefix(txParams.gasPrice || '0x4a817c800'), 16)
|
||||||
|
var txFee = gasCost.mul(gasPrice)
|
||||||
|
var txValue = new BN(ethUtil.stripHexPrefix(txParams.value || '0x0'), 16)
|
||||||
|
var maxCost = txValue.add(txFee)
|
||||||
|
|
||||||
|
var balanceBn = new BN(ethUtil.stripHexPrefix(balance), 16)
|
||||||
|
return maxCost.gt(balanceBn)
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfirmTxScreen.prototype.buyEth = function (address, event) {
|
||||||
|
event.stopPropagation()
|
||||||
|
this.props.dispatch(actions.buyEthView(address))
|
||||||
|
}
|
||||||
|
|
||||||
ConfirmTxScreen.prototype.sendTransaction = function (txData, event) {
|
ConfirmTxScreen.prototype.sendTransaction = function (txData, event) {
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
|
@ -36,24 +36,40 @@ button {
|
|||||||
font-family: 'Montserrat Bold';
|
font-family: 'Montserrat Bold';
|
||||||
outline: none;
|
outline: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-shadow: 0px 3px 6px rgba(247, 134, 28, 0.36);
|
|
||||||
/*margin: 10px;*/
|
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
border: none;
|
border: none;
|
||||||
background: #F7861C;
|
|
||||||
color: white;
|
color: white;
|
||||||
transform-origin: center center;
|
transform-origin: center center;
|
||||||
transition: transform 50ms ease-in;
|
transition: transform 50ms ease-in;
|
||||||
|
/* default orange */
|
||||||
|
background: rgba(247, 134, 28, 1);
|
||||||
|
box-shadow: 0px 3px 6px rgba(247, 134, 28, 0.36);
|
||||||
|
}
|
||||||
|
|
||||||
|
button.btn-green {
|
||||||
|
background: rgba(106, 195, 96, 1);
|
||||||
|
box-shadow: 0px 3px 6px rgba(106, 195, 96, 0.36);
|
||||||
|
}
|
||||||
|
|
||||||
|
button.btn-red {
|
||||||
|
background: rgba(254, 35, 17, 1);
|
||||||
|
box-shadow: 0px 3px 6px rgba(254, 35, 17, 0.36);
|
||||||
|
}
|
||||||
|
|
||||||
|
button[disabled] {
|
||||||
|
cursor: not-allowed;
|
||||||
|
background: rgba(197, 197, 197, 1);
|
||||||
|
box-shadow: 0px 3px 6px rgba(197, 197, 197, 0.36);
|
||||||
}
|
}
|
||||||
|
|
||||||
button.spaced {
|
button.spaced {
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button:hover {
|
button:not([disabled]):hover {
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
button:active {
|
button:not([disabled]):active {
|
||||||
transform: scale(0.95);
|
transform: scale(0.95);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +240,7 @@ function reduceApp (state, action) {
|
|||||||
name: 'confTx',
|
name: 'confTx',
|
||||||
context: 0,
|
context: 0,
|
||||||
},
|
},
|
||||||
transForward: true,
|
transForward: action.transForward,
|
||||||
warning: null,
|
warning: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -408,7 +408,7 @@ function reduceApp (state, action) {
|
|||||||
transForward: true,
|
transForward: true,
|
||||||
currentView: {
|
currentView: {
|
||||||
name: 'buyEth',
|
name: 'buyEth',
|
||||||
context: appState.currentView.context,
|
context: appState.currentView.name,
|
||||||
},
|
},
|
||||||
buyView: {
|
buyView: {
|
||||||
subview: 'buyForm',
|
subview: 'buyForm',
|
||||||
|
Loading…
Reference in New Issue
Block a user