aboutsummaryrefslogtreecommitdiffstats
path: root/old-ui/app
diff options
context:
space:
mode:
authorKevin Serrano <kevgagser@gmail.com>2018-10-15 08:32:29 +0800
committerGitHub <noreply@github.com>2018-10-15 08:32:29 +0800
commit85884b21afe6e5e85b58123b24e72776d1437cc6 (patch)
tree6dbec947089691c0dffd5febbe6e92c1f712e40f /old-ui/app
parentdb981b827b07c946e17d3a8aeaefd2143c236ef7 (diff)
parent7f6b488c04e6ea12b2ef24ac936b6a236ad904c2 (diff)
downloadtangerine-wallet-browser-85884b21afe6e5e85b58123b24e72776d1437cc6.tar.gz
tangerine-wallet-browser-85884b21afe6e5e85b58123b24e72776d1437cc6.tar.zst
tangerine-wallet-browser-85884b21afe6e5e85b58123b24e72776d1437cc6.zip
Merge pull request #5512 from MetaMask/v4.14.0
Version 4.14.0
Diffstat (limited to 'old-ui/app')
-rw-r--r--old-ui/app/account-detail.js5
-rw-r--r--old-ui/app/add-suggested-token.js202
-rw-r--r--old-ui/app/add-token.js2
-rw-r--r--old-ui/app/app.js6
-rw-r--r--old-ui/app/components/app-bar.js11
-rw-r--r--old-ui/app/components/notice.js17
-rw-r--r--old-ui/app/components/pending-typed-msg-details.js3
-rw-r--r--old-ui/app/components/typed-message-renderer.js27
-rw-r--r--old-ui/app/info.js1
9 files changed, 263 insertions, 11 deletions
diff --git a/old-ui/app/account-detail.js b/old-ui/app/account-detail.js
index c67f0cf71..d240fc38e 100644
--- a/old-ui/app/account-detail.js
+++ b/old-ui/app/account-detail.js
@@ -32,6 +32,7 @@ function mapStateToProps (state) {
currentCurrency: state.metamask.currentCurrency,
currentAccountTab: state.metamask.currentAccountTab,
tokens: state.metamask.tokens,
+ suggestedTokens: state.metamask.suggestedTokens,
computedBalances: state.metamask.computedBalances,
}
}
@@ -49,6 +50,10 @@ AccountDetailScreen.prototype.render = function () {
var account = props.accounts[selected]
const { network, conversionRate, currentCurrency } = props
+ if (Object.keys(props.suggestedTokens).length > 0) {
+ this.props.dispatch(actions.showAddSuggestedTokenPage())
+ }
+
return (
h('.account-detail-section.full-flex-height', [
diff --git a/old-ui/app/add-suggested-token.js b/old-ui/app/add-suggested-token.js
new file mode 100644
index 000000000..ea534b7da
--- /dev/null
+++ b/old-ui/app/add-suggested-token.js
@@ -0,0 +1,202 @@
+const inherits = require('util').inherits
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const connect = require('react-redux').connect
+const actions = require('../../ui/app/actions')
+const Tooltip = require('./components/tooltip.js')
+const ethUtil = require('ethereumjs-util')
+const Copyable = require('./components/copyable')
+const addressSummary = require('./util').addressSummary
+
+
+module.exports = connect(mapStateToProps)(AddSuggestedTokenScreen)
+
+function mapStateToProps (state) {
+ return {
+ identities: state.metamask.identities,
+ suggestedTokens: state.metamask.suggestedTokens,
+ }
+}
+
+inherits(AddSuggestedTokenScreen, Component)
+function AddSuggestedTokenScreen () {
+ this.state = {
+ warning: null,
+ }
+ Component.call(this)
+}
+
+AddSuggestedTokenScreen.prototype.render = function () {
+ const state = this.state
+ const props = this.props
+ const { warning } = state
+ const key = Object.keys(props.suggestedTokens)[0]
+ const { address, symbol, decimals } = props.suggestedTokens[key]
+
+ return (
+ h('.flex-column.flex-grow', [
+
+ // subtitle and nav
+ h('.section-title.flex-row.flex-center', [
+ h('h2.page-subtitle', 'Add Suggested Token'),
+ ]),
+
+ h('.error', {
+ style: {
+ display: warning ? 'block' : 'none',
+ padding: '0 20px',
+ textAlign: 'center',
+ },
+ }, warning),
+
+ // conf view
+ h('.flex-column.flex-justify-center.flex-grow.select-none', [
+ h('.flex-space-around', {
+ style: {
+ padding: '20px',
+ },
+ }, [
+
+ h('div', [
+ h(Tooltip, {
+ position: 'top',
+ title: 'The contract of the actual token contract. Click for more info.',
+ }, [
+ h('a', {
+ style: { fontWeight: 'bold', paddingRight: '10px'},
+ href: 'https://support.metamask.io/kb/article/24-what-is-a-token-contract-address',
+ target: '_blank',
+ }, [
+ h('span', 'Token Contract Address '),
+ h('i.fa.fa-question-circle'),
+ ]),
+ ]),
+ ]),
+
+ h('div', {
+ style: { display: 'flex' },
+ }, [
+ h(Copyable, {
+ value: ethUtil.toChecksumAddress(address),
+ }, [
+ h('span#token-address', {
+ style: {
+ width: 'inherit',
+ flex: '1 0 auto',
+ height: '30px',
+ margin: '8px',
+ display: 'flex',
+ },
+ }, addressSummary(address, 24, 4, false)),
+ ]),
+ ]),
+
+ h('div', [
+ h('span', {
+ style: { fontWeight: 'bold', paddingRight: '10px'},
+ }, 'Token Symbol'),
+ ]),
+
+ h('div', { style: {display: 'flex'} }, [
+ h('p#token_symbol', {
+ style: {
+ width: 'inherit',
+ flex: '1 0 auto',
+ height: '30px',
+ margin: '8px',
+ },
+ }, symbol),
+ ]),
+
+ h('div', [
+ h('span', {
+ style: { fontWeight: 'bold', paddingRight: '10px'},
+ }, 'Decimals of Precision'),
+ ]),
+
+ h('div', { style: {display: 'flex'} }, [
+ h('p#token_decimals', {
+ type: 'number',
+ style: {
+ width: 'inherit',
+ flex: '1 0 auto',
+ height: '30px',
+ margin: '8px',
+ },
+ }, decimals),
+ ]),
+
+ h('button', {
+ style: {
+ alignSelf: 'center',
+ margin: '8px',
+ },
+ onClick: (event) => {
+ this.props.dispatch(actions.removeSuggestedTokens())
+ },
+ }, 'Cancel'),
+
+ h('button', {
+ style: {
+ alignSelf: 'center',
+ margin: '8px',
+ },
+ onClick: (event) => {
+ const valid = this.validateInputs({ address, symbol, decimals })
+ if (!valid) return
+
+ this.props.dispatch(actions.addToken(address.trim(), symbol.trim(), decimals))
+ .then(() => {
+ this.props.dispatch(actions.removeSuggestedTokens())
+ })
+ },
+ }, 'Add'),
+ ]),
+ ]),
+ ])
+ )
+}
+
+AddSuggestedTokenScreen.prototype.componentWillMount = function () {
+ if (typeof global.ethereumProvider === 'undefined') return
+}
+
+AddSuggestedTokenScreen.prototype.validateInputs = function (opts) {
+ let msg = ''
+ const identitiesList = Object.keys(this.props.identities)
+ const { address, symbol, decimals } = opts
+ const standardAddress = ethUtil.addHexPrefix(address).toLowerCase()
+
+ const validAddress = ethUtil.isValidAddress(address)
+ if (!validAddress) {
+ msg += 'Address is invalid.'
+ }
+
+ const validDecimals = decimals >= 0 && decimals <= 36
+ if (!validDecimals) {
+ msg += 'Decimals must be at least 0, and not over 36. '
+ }
+
+ const symbolLen = symbol.trim().length
+ const validSymbol = symbolLen > 0 && symbolLen < 10
+ if (!validSymbol) {
+ msg += 'Symbol must be between 0 and 10 characters.'
+ }
+
+ const ownAddress = identitiesList.includes(standardAddress)
+ if (ownAddress) {
+ msg = 'Personal address detected. Input the token contract address.'
+ }
+
+ const isValid = validAddress && validDecimals && !ownAddress
+
+ if (!isValid) {
+ this.setState({
+ warning: msg,
+ })
+ } else {
+ this.setState({ warning: null })
+ }
+
+ return isValid
+}
diff --git a/old-ui/app/add-token.js b/old-ui/app/add-token.js
index e869ac39a..6cf211636 100644
--- a/old-ui/app/add-token.js
+++ b/old-ui/app/add-token.js
@@ -196,7 +196,7 @@ AddTokenScreen.prototype.validateInputs = function () {
msg += 'Address is invalid.'
}
- const validDecimals = decimals >= 0 && decimals < 36
+ const validDecimals = decimals >= 0 && decimals <= 36
if (!validDecimals) {
msg += 'Decimals must be at least 0, and not over 36. '
}
diff --git a/old-ui/app/app.js b/old-ui/app/app.js
index d3e9e823b..9be21ebad 100644
--- a/old-ui/app/app.js
+++ b/old-ui/app/app.js
@@ -23,6 +23,7 @@ const generateLostAccountsNotice = require('../lib/lost-accounts-notice')
// other views
const ConfigScreen = require('./config')
const AddTokenScreen = require('./add-token')
+const AddSuggestedTokenScreen = require('./add-suggested-token')
const Import = require('./accounts/import')
const InfoScreen = require('./info')
const NewUiAnnouncement = require('./new-ui-annoucement')
@@ -74,6 +75,7 @@ function mapStateToProps (state) {
lostAccounts: state.metamask.lostAccounts,
frequentRpcList: state.metamask.frequentRpcList || [],
featureFlags,
+ suggestedTokens: state.metamask.suggestedTokens,
// state needed to get account dropdown temporarily rendering from app bar
identities,
@@ -236,6 +238,10 @@ App.prototype.renderPrimary = function () {
log.debug('rendering add-token screen from unlock screen.')
return h(AddTokenScreen, {key: 'add-token'})
+ case 'add-suggested-token':
+ log.debug('rendering add-suggested-token screen from unlock screen.')
+ return h(AddSuggestedTokenScreen, {key: 'add-suggested-token'})
+
case 'config':
log.debug('rendering config screen')
return h(ConfigScreen, {key: 'config'})
diff --git a/old-ui/app/components/app-bar.js b/old-ui/app/components/app-bar.js
index 8ab647efd..234c06a01 100644
--- a/old-ui/app/components/app-bar.js
+++ b/old-ui/app/components/app-bar.js
@@ -350,11 +350,14 @@ module.exports = class AppBar extends Component {
}
}
- renderCommonRpc (rpcList, {rpcTarget}) {
+ renderCommonRpc (rpcList, provider) {
const {dispatch} = this.props
+ const reversedRpcList = rpcList.slice().reverse()
- return rpcList.map((rpc) => {
- if ((rpc === LOCALHOST_RPC_URL) || (rpc === rpcTarget)) {
+ return reversedRpcList.map((rpc) => {
+ const currentRpcTarget = provider.type === 'rpc' && rpc === provider.rpcTarget
+
+ if ((rpc === LOCALHOST_RPC_URL) || currentRpcTarget) {
return null
} else {
return h(DropdownMenuItem, {
@@ -364,7 +367,7 @@ module.exports = class AppBar extends Component {
}, [
h('i.fa.fa-question-circle.fa-lg.menu-icon'),
rpc,
- rpcTarget === rpc
+ currentRpcTarget
? h('.check', '✓')
: null,
])
diff --git a/old-ui/app/components/notice.js b/old-ui/app/components/notice.js
index 09d461c7b..1ec254555 100644
--- a/old-ui/app/components/notice.js
+++ b/old-ui/app/components/notice.js
@@ -116,12 +116,25 @@ Notice.prototype.render = function () {
)
}
+Notice.prototype.setInitialDisclaimerState = function () {
+ if (document.getElementsByClassName('notice-box')[0].clientHeight < 310) {
+ this.setState({disclaimerDisabled: false})
+ }
+}
+
Notice.prototype.componentDidMount = function () {
// eslint-disable-next-line react/no-find-dom-node
var node = findDOMNode(this)
linker.setupListener(node)
- if (document.getElementsByClassName('notice-box')[0].clientHeight < 310) {
- this.setState({disclaimerDisabled: false})
+ this.setInitialDisclaimerState()
+}
+
+Notice.prototype.componentDidUpdate = function (prevProps) {
+ const { notice: { id } = {} } = this.props
+ const { notice: { id: prevNoticeId } = {} } = prevProps
+
+ if (id !== prevNoticeId) {
+ this.setInitialDisclaimerState()
}
}
diff --git a/old-ui/app/components/pending-typed-msg-details.js b/old-ui/app/components/pending-typed-msg-details.js
index b5fd29f71..f95bf43a7 100644
--- a/old-ui/app/components/pending-typed-msg-details.js
+++ b/old-ui/app/components/pending-typed-msg-details.js
@@ -21,7 +21,7 @@ PendingMsgDetails.prototype.render = function () {
var identity = state.identities[address] || { address: address }
var account = state.accounts[address] || { address: address }
- var { data } = msgParams
+ var { data, version } = msgParams
return (
h('div', {
@@ -48,6 +48,7 @@ PendingMsgDetails.prototype.render = function () {
h('label.font-small', { style: { display: 'block' } }, 'YOU ARE SIGNING'),
h(TypedMessageRenderer, {
value: data,
+ version,
style: {
height: '215px',
},
diff --git a/old-ui/app/components/typed-message-renderer.js b/old-ui/app/components/typed-message-renderer.js
index 19e46f4fc..0dc673b8a 100644
--- a/old-ui/app/components/typed-message-renderer.js
+++ b/old-ui/app/components/typed-message-renderer.js
@@ -2,6 +2,7 @@ const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
const extend = require('xtend')
+const { ObjectInspector } = require('react-inspector')
module.exports = TypedMessageRenderer
@@ -12,8 +13,16 @@ function TypedMessageRenderer () {
TypedMessageRenderer.prototype.render = function () {
const props = this.props
- const { value, style } = props
- const text = renderTypedData(value)
+ const { value, version, style } = props
+ let text
+ switch (version) {
+ case 'V1':
+ text = renderTypedData(value)
+ break
+ case 'V3':
+ text = renderTypedDataV3(value)
+ break
+ }
const defaultStyle = extend({
width: '315px',
@@ -44,3 +53,17 @@ function renderTypedData (values) {
])
})
}
+
+function renderTypedDataV3 (values) {
+ const { domain, message } = JSON.parse(values)
+ return [
+ domain ? h('div', [
+ h('h1', 'Domain'),
+ h(ObjectInspector, { data: domain, expandLevel: 1, name: 'domain' }),
+ ]) : '',
+ message ? h('div', [
+ h('h1', 'Message'),
+ h(ObjectInspector, { data: message, expandLevel: 1, name: 'message' }),
+ ]) : '',
+ ]
+}
diff --git a/old-ui/app/info.js b/old-ui/app/info.js
index d79b8a3d2..936d270da 100644
--- a/old-ui/app/info.js
+++ b/old-ui/app/info.js
@@ -138,7 +138,6 @@ InfoScreen.prototype.render = function () {
h('div.fa.fa-envelope', [
h('a.info', {
target: '_blank',
- style: { width: '85vw' },
href: 'mailto:help@metamask.io?subject=Feedback',
}, 'Email us!'),
]),