aboutsummaryrefslogtreecommitdiffstats
path: root/old-ui
diff options
context:
space:
mode:
Diffstat (limited to 'old-ui')
-rw-r--r--old-ui/app/app.js12
-rw-r--r--old-ui/app/components/app-bar.js15
-rw-r--r--old-ui/app/components/balance.js11
-rw-r--r--old-ui/app/components/eth-balance.js12
-rw-r--r--old-ui/app/components/pending-tx.js16
-rw-r--r--old-ui/app/config.js132
-rw-r--r--old-ui/app/provider-approval.js64
-rw-r--r--old-ui/app/util.js8
8 files changed, 243 insertions, 27 deletions
diff --git a/old-ui/app/app.js b/old-ui/app/app.js
index 9be21ebad..2d364ef6f 100644
--- a/old-ui/app/app.js
+++ b/old-ui/app/app.js
@@ -33,6 +33,7 @@ const BuyView = require('./components/buy-button-subview')
const HDCreateVaultComplete = require('./keychains/hd/create-vault-complete')
const HDRestoreVaultScreen = require('./keychains/hd/restore-vault')
const RevealSeedConfirmation = require('./keychains/hd/recover-seed/confirmation')
+const ProviderApproval = require('./provider-approval')
module.exports = connect(mapStateToProps)(App)
@@ -49,6 +50,7 @@ function mapStateToProps (state) {
noActiveNotices,
seedWords,
featureFlags,
+ providerRequests,
} = state.metamask
const selected = address || Object.keys(accounts)[0]
@@ -73,8 +75,9 @@ function mapStateToProps (state) {
forgottenPassword: state.appState.forgottenPassword,
nextUnreadNotice: state.metamask.nextUnreadNotice,
lostAccounts: state.metamask.lostAccounts,
- frequentRpcList: state.metamask.frequentRpcList || [],
+ frequentRpcListDetail: state.metamask.frequentRpcListDetail || [],
featureFlags,
+ providerRequests,
suggestedTokens: state.metamask.suggestedTokens,
// state needed to get account dropdown temporarily rendering from app bar
@@ -147,7 +150,7 @@ App.prototype.renderLoadingIndicator = function ({ isLoading, isLoadingNetwork,
App.prototype.renderPrimary = function () {
log.debug('rendering primary')
var props = this.props
- const {isMascara, isOnboarding} = props
+ const {isMascara, isOnboarding, providerRequests} = props
if (isMascara && isOnboarding) {
return h(MascaraFirstTime)
@@ -215,6 +218,11 @@ App.prototype.renderPrimary = function () {
return h(HDCreateVaultComplete, {key: 'HDCreateVaultComplete'})
}
+ if (providerRequests && providerRequests.length > 0) {
+ log.debug('rendering provider API approval screen')
+ return h(ProviderApproval, { origin: providerRequests[0].origin })
+ }
+
// show current view
switch (props.currentView.name) {
diff --git a/old-ui/app/components/app-bar.js b/old-ui/app/components/app-bar.js
index 234c06a01..fa8e499ed 100644
--- a/old-ui/app/components/app-bar.js
+++ b/old-ui/app/components/app-bar.js
@@ -17,7 +17,7 @@ module.exports = class AppBar extends Component {
static propTypes = {
dispatch: PropTypes.func.isRequired,
- frequentRpcList: PropTypes.array.isRequired,
+ frequentRpcListDetail: PropTypes.array.isRequired,
isMascara: PropTypes.bool.isRequired,
isOnboarding: PropTypes.bool.isRequired,
identities: PropTypes.any.isRequired,
@@ -196,7 +196,7 @@ module.exports = class AppBar extends Component {
renderNetworkDropdown () {
const {
dispatch,
- frequentRpcList: rpcList,
+ frequentRpcListDetail: rpcList,
provider,
} = this.props
const {
@@ -321,8 +321,8 @@ module.exports = class AppBar extends Component {
])
}
- renderCustomOption ({ rpcTarget, type }) {
- const {dispatch} = this.props
+ renderCustomOption ({ rpcTarget, type, ticker }) {
+ const {dispatch, network} = this.props
if (type !== 'rpc') {
return null
@@ -340,7 +340,7 @@ module.exports = class AppBar extends Component {
default:
return h(DropdownMenuItem, {
key: rpcTarget,
- onClick: () => dispatch(actions.setRpcTarget(rpcTarget)),
+ onClick: () => dispatch(actions.setRpcTarget(rpcTarget, network, ticker)),
closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
}, [
h('i.fa.fa-question-circle.fa-lg.menu-icon'),
@@ -354,7 +354,8 @@ module.exports = class AppBar extends Component {
const {dispatch} = this.props
const reversedRpcList = rpcList.slice().reverse()
- return reversedRpcList.map((rpc) => {
+ return reversedRpcList.map((entry) => {
+ const rpc = entry.rpcUrl
const currentRpcTarget = provider.type === 'rpc' && rpc === provider.rpcTarget
if ((rpc === LOCALHOST_RPC_URL) || currentRpcTarget) {
@@ -363,7 +364,7 @@ module.exports = class AppBar extends Component {
return h(DropdownMenuItem, {
key: `common${rpc}`,
closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
- onClick: () => dispatch(actions.setRpcTarget(rpc)),
+ onClick: () => dispatch(actions.setRpcTarget(rpc, entry.chainId, entry.ticker)),
}, [
h('i.fa.fa-question-circle.fa-lg.menu-icon'),
rpc,
diff --git a/old-ui/app/components/balance.js b/old-ui/app/components/balance.js
index 57ca84564..8995f961f 100644
--- a/old-ui/app/components/balance.js
+++ b/old-ui/app/components/balance.js
@@ -1,12 +1,18 @@
const Component = require('react').Component
const h = require('react-hyperscript')
+const connect = require('react-redux').connect
const inherits = require('util').inherits
const formatBalance = require('../util').formatBalance
const generateBalanceObject = require('../util').generateBalanceObject
const Tooltip = require('./tooltip.js')
const FiatValue = require('./fiat-value.js')
-module.exports = EthBalanceComponent
+module.exports = connect(mapStateToProps)(EthBalanceComponent)
+function mapStateToProps (state) {
+ return {
+ ticker: state.metamask.ticker,
+ }
+}
inherits(EthBalanceComponent, Component)
function EthBalanceComponent () {
@@ -16,9 +22,10 @@ function EthBalanceComponent () {
EthBalanceComponent.prototype.render = function () {
var props = this.props
let { value } = props
+ const { ticker } = props
var style = props.style
var needsParse = this.props.needsParse !== undefined ? this.props.needsParse : true
- value = value ? formatBalance(value, 6, needsParse) : '...'
+ value = value ? formatBalance(value, 6, needsParse, ticker) : '...'
var width = props.width
return (
diff --git a/old-ui/app/components/eth-balance.js b/old-ui/app/components/eth-balance.js
index 4f538fd31..4458e6a9a 100644
--- a/old-ui/app/components/eth-balance.js
+++ b/old-ui/app/components/eth-balance.js
@@ -1,12 +1,18 @@
const Component = require('react').Component
const h = require('react-hyperscript')
+const connect = require('react-redux').connect
const inherits = require('util').inherits
const formatBalance = require('../util').formatBalance
const generateBalanceObject = require('../util').generateBalanceObject
const Tooltip = require('./tooltip.js')
const FiatValue = require('./fiat-value.js')
-module.exports = EthBalanceComponent
+module.exports = connect(mapStateToProps)(EthBalanceComponent)
+function mapStateToProps (state) {
+ return {
+ ticker: state.metamask.ticker,
+ }
+}
inherits(EthBalanceComponent, Component)
function EthBalanceComponent () {
@@ -16,9 +22,9 @@ function EthBalanceComponent () {
EthBalanceComponent.prototype.render = function () {
var props = this.props
let { value } = props
- const { style, width } = props
+ const { ticker, style, width } = props
var needsParse = this.props.needsParse !== undefined ? this.props.needsParse : true
- value = value ? formatBalance(value, 6, needsParse) : '...'
+ value = value ? formatBalance(value, 6, needsParse, ticker) : '...'
return (
diff --git a/old-ui/app/components/pending-tx.js b/old-ui/app/components/pending-tx.js
index c8132539c..35e81210e 100644
--- a/old-ui/app/components/pending-tx.js
+++ b/old-ui/app/components/pending-tx.js
@@ -1,4 +1,5 @@
const Component = require('react').Component
+const connect = require('react-redux').connect
const h = require('react-hyperscript')
const inherits = require('util').inherits
const actions = require('../../../ui/app/actions')
@@ -19,7 +20,9 @@ const BNInput = require('./bn-as-decimal-input')
const MIN_GAS_PRICE_BN = new BN('0')
const MIN_GAS_LIMIT_BN = new BN('21000')
-module.exports = PendingTx
+module.exports = connect()(PendingTx)
+
+
inherits(PendingTx, Component)
function PendingTx () {
Component.call(this)
@@ -445,7 +448,8 @@ PendingTx.prototype.onSubmit = function (event) {
const txMeta = this.gatherTxMeta()
const valid = this.checkValidity()
this.setState({ valid, submitting: true })
- if (valid && this.verifyGasParams()) {
+ const validGasParams = this.verifyGasParams()
+ if (valid && validGasParams) {
this.props.sendTransaction(txMeta, event)
} else {
this.props.dispatch(actions.displayWarning('Invalid Gas Parameters'))
@@ -488,8 +492,12 @@ PendingTx.prototype.verifyGasParams = function () {
)
}
-PendingTx.prototype._notZeroOrEmptyString = function (obj) {
- return obj !== '' && obj !== '0x0'
+PendingTx.prototype._notZeroOrEmptyString = function (value) {
+ // allow undefined values
+ if (value === undefined) return true
+ // Geth will return '0x', and ganache-core v2.2.1 will return '0x0'
+ const valueIsEmpty = !value || value === '0x' || value === '0x0'
+ return !valueIsEmpty
}
PendingTx.prototype.bnMultiplyByFraction = function (targetBN, numerator, denominator) {
diff --git a/old-ui/app/config.js b/old-ui/app/config.js
index 392a6dba7..2a0643919 100644
--- a/old-ui/app/config.js
+++ b/old-ui/app/config.js
@@ -68,7 +68,7 @@ ConfigScreen.prototype.render = function () {
currentProviderDisplay(metamaskState),
- h('div', { style: {display: 'flex'} }, [
+ h('div', { style: {display: 'block'} }, [
h('input#new_rpc', {
placeholder: 'New RPC URL',
style: {
@@ -81,7 +81,70 @@ ConfigScreen.prototype.render = function () {
if (event.key === 'Enter') {
var element = event.target
var newRpc = element.value
- rpcValidation(newRpc, state)
+ var chainid = document.querySelector('input#chainid')
+ var ticker = document.querySelector('input#ticker')
+ var nickname = document.querySelector('input#nickname')
+ rpcValidation(newRpc, chainid.value, ticker.value, nickname.value, state)
+ }
+ },
+ }),
+ h('br'),
+ h('input#chainid', {
+ placeholder: 'ChainId (optional)',
+ style: {
+ width: 'inherit',
+ flex: '1 0 auto',
+ height: '30px',
+ margin: '8px',
+ },
+ onKeyPress (event) {
+ if (event.key === 'Enter') {
+ var element = document.querySelector('input#new_rpc')
+ var newRpc = element.value
+ var chainid = document.querySelector('input#chainid')
+ var ticker = document.querySelector('input#ticker')
+ var nickname = document.querySelector('input#nickname')
+ rpcValidation(newRpc, chainid.value, ticker.value, nickname.value, state)
+ }
+ },
+ }),
+ h('br'),
+ h('input#ticker', {
+ placeholder: 'Symbol (optional)',
+ style: {
+ width: 'inherit',
+ flex: '1 0 auto',
+ height: '30px',
+ margin: '8px',
+ },
+ onKeyPress (event) {
+ if (event.key === 'Enter') {
+ var element = document.querySelector('input#new_rpc')
+ var newRpc = element.value
+ var chainid = document.querySelector('input#chainid')
+ var ticker = document.querySelector('input#ticker')
+ var nickname = document.querySelector('input#nickname')
+ rpcValidation(newRpc, chainid.value, ticker.value, nickname.value, state)
+ }
+ },
+ }),
+ h('br'),
+ h('input#nickname', {
+ placeholder: 'Nickname (optional)',
+ style: {
+ width: 'inherit',
+ flex: '1 0 auto',
+ height: '30px',
+ margin: '8px',
+ },
+ onKeyPress (event) {
+ if (event.key === 'Enter') {
+ var element = document.querySelector('input#new_rpc')
+ var newRpc = element.value
+ var chainid = document.querySelector('input#chainid')
+ var ticker = document.querySelector('input#ticker')
+ var nickname = document.querySelector('input#nickname')
+ rpcValidation(newRpc, chainid.value, ticker.value, nickname.value, state)
}
},
}),
@@ -93,7 +156,10 @@ ConfigScreen.prototype.render = function () {
event.preventDefault()
var element = document.querySelector('input#new_rpc')
var newRpc = element.value
- rpcValidation(newRpc, state)
+ var chainid = document.querySelector('input#chainid')
+ var ticker = document.querySelector('input#ticker')
+ var nickname = document.querySelector('input#nickname')
+ rpcValidation(newRpc, chainid.value, ticker.value, nickname.value, state)
},
}, 'Save'),
]),
@@ -139,6 +205,62 @@ ConfigScreen.prototype.render = function () {
marginTop: '20px',
},
}, [
+ h('p', {
+ style: {
+ fontFamily: 'Montserrat Light',
+ fontSize: '13px',
+ },
+ }, 'Clear privacy data so all websites must request access to view account information again.'),
+ h('br'),
+ h('button', {
+ style: {
+ alignSelf: 'center',
+ },
+ onClick (event) {
+ event.preventDefault()
+ state.dispatch(actions.clearApprovedOrigins())
+ },
+ }, 'Clear privacy data'),
+ ]),
+
+ h('hr.horizontal-line'),
+
+ h('div', {
+ style: {
+ marginTop: '20px',
+ },
+ }, [
+ h('p', {
+ style: {
+ fontFamily: 'Montserrat Light',
+ fontSize: '13px',
+ },
+ }, metamaskState.featureFlags.privacyMode ?
+ 'Websites will be able to view your account information.' :
+ 'Websites must request access to view your account information.'
+ ),
+ h('br'),
+ h('button', {
+ style: {
+ alignSelf: 'center',
+ },
+ onClick (event) {
+ event.preventDefault()
+ state.dispatch(actions.setFeatureFlag('privacyMode', !metamaskState.featureFlags.privacyMode))
+ },
+ }, metamaskState.featureFlags.privacyMode ?
+ 'Disable privacy mode' :
+ 'Enable privacy mode'
+ ),
+ ]),
+
+ h('hr.horizontal-line'),
+
+ h('div', {
+ style: {
+ marginTop: '20px',
+ },
+ }, [
h('button', {
style: {
alignSelf: 'center',
@@ -189,9 +311,9 @@ ConfigScreen.prototype.render = function () {
)
}
-function rpcValidation (newRpc, state) {
+function rpcValidation (newRpc, chainid, ticker = 'ETH', nickname = '', state) {
if (validUrl.isWebUri(newRpc)) {
- state.dispatch(actions.setRpcTarget(newRpc))
+ state.dispatch(actions.setRpcTarget(newRpc, chainid, ticker, nickname))
} else {
var appendedRpc = `http://${newRpc}`
if (validUrl.isWebUri(appendedRpc)) {
diff --git a/old-ui/app/provider-approval.js b/old-ui/app/provider-approval.js
new file mode 100644
index 000000000..c4c7ff64d
--- /dev/null
+++ b/old-ui/app/provider-approval.js
@@ -0,0 +1,64 @@
+import PropTypes from 'prop-types'
+import React, { Component } from 'react'
+import { approveProviderRequest, rejectProviderRequest } from '../../ui/app/actions'
+import { connect } from 'react-redux'
+class ProviderApproval extends Component {
+ render () {
+ const { approveProviderRequest, origin, rejectProviderRequest } = this.props
+ return (
+ <div className="flex-column flex-grow">
+ <style dangerouslySetInnerHTML={{__html: `
+ .provider_approval_actions {
+ display: flex;
+ justify-content: flex-end;
+ margin: 14px 25px;
+ }
+ .provider_approval_actions button {
+ margin-left: 10px;
+ text-transform: uppercase;
+ }
+ .provider_approval_content {
+ padding: 0 25px;
+ }
+ .provider_approval_origin {
+ font-weight: bold;
+ margin: 14px 0;
+ }
+ `}} />
+ <div className="section-title flex-row flex-center">
+ <i
+ className="fa fa-arrow-left fa-lg cursor-pointer"
+ onClick={() => { rejectProviderRequest(origin) }} />
+ <h2 className="page-subtitle">Web3 API Request</h2>
+ </div>
+ <div className="provider_approval_content">
+ {"The domain listed below is requesting access to the Ethereum blockchain and to view your current account. Always double check that you're on the correct site before approving access."}
+ <div className="provider_approval_origin">{origin}</div>
+ </div>
+ <div className="provider_approval_actions">
+ <button
+ className="btn-green"
+ onClick={() => { approveProviderRequest(origin) }}>APPROVE</button>
+ <button
+ className="cancel btn-red"
+ onClick={() => { rejectProviderRequest(origin) }}>REJECT</button>
+ </div>
+ </div>
+ )
+ }
+}
+
+ProviderApproval.propTypes = {
+ approveProviderRequest: PropTypes.func,
+ origin: PropTypes.string,
+ rejectProviderRequest: PropTypes.func,
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ approveProviderRequest: origin => dispatch(approveProviderRequest(origin)),
+ rejectProviderRequest: origin => dispatch(rejectProviderRequest(origin)),
+ }
+}
+
+module.exports = connect(null, mapDispatchToProps)(ProviderApproval)
diff --git a/old-ui/app/util.js b/old-ui/app/util.js
index 962832ce7..40e79b88c 100644
--- a/old-ui/app/util.js
+++ b/old-ui/app/util.js
@@ -102,7 +102,7 @@ function parseBalance (balance) {
// Takes wei hex, returns an object with three properties.
// Its "formatted" property is what we generally use to render values.
-function formatBalance (balance, decimalsToKeep, needsParse = true) {
+function formatBalance (balance, decimalsToKeep, needsParse = true, ticker = 'ETH') {
var parsed = needsParse ? parseBalance(balance) : balance.split('.')
var beforeDecimal = parsed[0]
var afterDecimal = parsed[1]
@@ -112,14 +112,14 @@ function formatBalance (balance, decimalsToKeep, needsParse = true) {
if (afterDecimal !== '0') {
var sigFigs = afterDecimal.match(/^0*(.{2})/) // default: grabs 2 most significant digits
if (sigFigs) { afterDecimal = sigFigs[0] }
- formatted = '0.' + afterDecimal + ' ETH'
+ formatted = '0.' + afterDecimal + ` ${ticker}`
}
} else {
- formatted = beforeDecimal + '.' + afterDecimal.slice(0, 3) + ' ETH'
+ formatted = beforeDecimal + '.' + afterDecimal.slice(0, 3) + ` ${ticker}`
}
} else {
afterDecimal += Array(decimalsToKeep).join('0')
- formatted = beforeDecimal + '.' + afterDecimal.slice(0, decimalsToKeep) + ' ETH'
+ formatted = beforeDecimal + '.' + afterDecimal.slice(0, decimalsToKeep) + ` ${ticker}`
}
return formatted
}