You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
363 lines
9.8 KiB
363 lines
9.8 KiB
const { Component } = require('react')
|
|
const PropTypes = require('prop-types')
|
|
const h = require('react-hyperscript')
|
|
const { connect } = require('react-redux')
|
|
const actions = require('./actions')
|
|
const infuraCurrencies = require('./infura-conversion.json')
|
|
const validUrl = require('valid-url')
|
|
const { exportAsFile } = require('./util')
|
|
const TabBar = require('./components/tab-bar')
|
|
const SimpleDropdown = require('./components/dropdowns/simple-dropdown')
|
|
|
|
const getInfuraCurrencyOptions = () => {
|
|
const sortedCurrencies = infuraCurrencies.objects.sort((a, b) => {
|
|
return a.quote.name.toLocaleLowerCase().localeCompare(b.quote.name.toLocaleLowerCase())
|
|
})
|
|
|
|
return sortedCurrencies.map(({ quote: { code, name } }) => {
|
|
return {
|
|
displayValue: `${code.toUpperCase()} - ${name}`,
|
|
key: code,
|
|
value: code,
|
|
}
|
|
})
|
|
}
|
|
|
|
class Settings extends Component {
|
|
constructor (props) {
|
|
super(props)
|
|
|
|
const { tab } = props
|
|
const activeTab = tab === 'info' ? 'info' : 'settings'
|
|
|
|
this.state = {
|
|
activeTab,
|
|
newRpc: '',
|
|
}
|
|
}
|
|
|
|
renderTabs () {
|
|
const { activeTab } = this.state
|
|
|
|
return h('div.settings__tabs', [
|
|
h(TabBar, {
|
|
tabs: [
|
|
{ content: 'Settings', key: 'settings' },
|
|
{ content: 'Info', key: 'info' },
|
|
],
|
|
defaultTab: activeTab,
|
|
tabSelected: key => this.setState({ activeTab: key }),
|
|
}),
|
|
])
|
|
}
|
|
|
|
renderCurrentConversion () {
|
|
const { metamask: { currentCurrency, conversionDate }, setCurrentCurrency } = this.props
|
|
|
|
return h('div.settings__content-row', [
|
|
h('div.settings__content-item', [
|
|
h('span', 'Current Conversion'),
|
|
h('span.settings__content-description', `Updated ${Date(conversionDate)}`),
|
|
]),
|
|
h('div.settings__content-item', [
|
|
h('div.settings__content-item-col', [
|
|
h(SimpleDropdown, {
|
|
placeholder: 'Select Currency',
|
|
options: getInfuraCurrencyOptions(),
|
|
selectedOption: currentCurrency,
|
|
onSelect: newCurrency => setCurrentCurrency(newCurrency),
|
|
}),
|
|
]),
|
|
]),
|
|
])
|
|
}
|
|
|
|
renderCurrentProvider () {
|
|
const { metamask: { provider = {} } } = this.props
|
|
let title, value, color
|
|
|
|
switch (provider.type) {
|
|
|
|
case 'mainnet':
|
|
title = 'Current Network'
|
|
value = 'Main Ethereum Network'
|
|
color = '#038789'
|
|
break
|
|
|
|
case 'ropsten':
|
|
title = 'Current Network'
|
|
value = 'Ropsten Test Network'
|
|
color = '#e91550'
|
|
break
|
|
|
|
case 'kovan':
|
|
title = 'Current Network'
|
|
value = 'Kovan Test Network'
|
|
color = '#690496'
|
|
break
|
|
|
|
case 'rinkeby':
|
|
title = 'Current Network'
|
|
value = 'Rinkeby Test Network'
|
|
color = '#ebb33f'
|
|
break
|
|
|
|
default:
|
|
title = 'Current RPC'
|
|
value = provider.rpcTarget
|
|
}
|
|
|
|
return h('div.settings__content-row', [
|
|
h('div.settings__content-item', title),
|
|
h('div.settings__content-item', [
|
|
h('div.settings__content-item-col', [
|
|
h('div.settings__provider-wrapper', [
|
|
h('div.settings__provider-icon', { style: { background: color } }),
|
|
h('div', value),
|
|
]),
|
|
]),
|
|
]),
|
|
])
|
|
}
|
|
|
|
renderNewRpcUrl () {
|
|
return (
|
|
h('div.settings__content-row', [
|
|
h('div.settings__content-item', [
|
|
h('span', 'New RPC URL'),
|
|
]),
|
|
h('div.settings__content-item', [
|
|
h('div.settings__content-item-col', [
|
|
h('input.settings__input', {
|
|
placeholder: 'New RPC URL',
|
|
onChange: event => this.setState({ newRpc: event.target.value }),
|
|
onKeyPress: event => {
|
|
if (event.key === 'Enter') {
|
|
this.validateRpc(this.state.newRpc)
|
|
}
|
|
},
|
|
}),
|
|
h('div.settings__rpc-save-button', {
|
|
onClick: event => {
|
|
event.preventDefault()
|
|
this.validateRpc(this.state.newRpc)
|
|
},
|
|
}, 'Save'),
|
|
]),
|
|
]),
|
|
])
|
|
)
|
|
}
|
|
|
|
validateRpc (newRpc) {
|
|
const { setRpcTarget, displayWarning } = this.props
|
|
|
|
if (validUrl.isWebUri(newRpc)) {
|
|
setRpcTarget(newRpc)
|
|
} else {
|
|
const appendedRpc = `http://${newRpc}`
|
|
|
|
if (validUrl.isWebUri(appendedRpc)) {
|
|
displayWarning('URIs require the appropriate HTTP/HTTPS prefix.')
|
|
} else {
|
|
displayWarning('Invalid RPC URI')
|
|
}
|
|
}
|
|
}
|
|
|
|
renderStateLogs () {
|
|
return (
|
|
h('div.settings__content-row', [
|
|
h('div.settings__content-item', [
|
|
h('div', 'State Logs'),
|
|
h(
|
|
'div.settings__content-description',
|
|
'State logs contain your public account addresses and sent transactions.'
|
|
),
|
|
]),
|
|
h('div.settings__content-item', [
|
|
h('div.settings__content-item-col', [
|
|
h('button.settings__clear-button', {
|
|
onClick (event) {
|
|
exportAsFile('MetaMask State Logs', window.logState())
|
|
},
|
|
}, 'Download State Logs'),
|
|
]),
|
|
]),
|
|
])
|
|
)
|
|
}
|
|
|
|
renderSeedWords () {
|
|
const { revealSeedConfirmation } = this.props
|
|
|
|
return (
|
|
h('div.settings__content-row', [
|
|
h('div.settings__content-item', 'Reveal Seed Words'),
|
|
h('div.settings__content-item', [
|
|
h('div.settings__content-item-col', [
|
|
h('button.settings__clear-button.settings__clear-button--red', {
|
|
onClick (event) {
|
|
event.preventDefault()
|
|
revealSeedConfirmation()
|
|
},
|
|
}, 'Reveal Seed Words'),
|
|
]),
|
|
]),
|
|
])
|
|
)
|
|
}
|
|
|
|
renderSettingsContent () {
|
|
const { warning } = this.props
|
|
|
|
return (
|
|
h('div.settings__content', [
|
|
warning && h('div.settings__error', warning),
|
|
this.renderCurrentConversion(),
|
|
// this.renderCurrentProvider(),
|
|
this.renderNewRpcUrl(),
|
|
this.renderStateLogs(),
|
|
this.renderSeedWords(),
|
|
])
|
|
)
|
|
}
|
|
|
|
renderLogo () {
|
|
return (
|
|
h('div.settings__info-logo-wrapper', [
|
|
h('img.settings__info-logo', { src: 'images/info-logo.png' }),
|
|
])
|
|
)
|
|
}
|
|
|
|
renderInfoLinks () {
|
|
return (
|
|
h('div.settings__content-item.settings__content-item--without-height', [
|
|
h('div.settings__info-link-header', 'Links'),
|
|
h('div.settings__info-link-item', [
|
|
h('a', {
|
|
href: 'https://metamask.io/privacy.html',
|
|
target: '_blank',
|
|
}, [
|
|
h('span.settings__info-link', 'Privacy Policy'),
|
|
]),
|
|
]),
|
|
h('div.settings__info-link-item', [
|
|
h('a', {
|
|
href: 'https://metamask.io/terms.html',
|
|
target: '_blank',
|
|
}, [
|
|
h('span.settings__info-link', 'Terms of Use'),
|
|
]),
|
|
]),
|
|
h('div.settings__info-link-item', [
|
|
h('a', {
|
|
href: 'https://metamask.io/attributions.html',
|
|
target: '_blank',
|
|
}, [
|
|
h('span.settings__info-link', 'Attributions'),
|
|
]),
|
|
]),
|
|
h('hr.settings__info-separator'),
|
|
h('div.settings__info-link-item', [
|
|
h('a', {
|
|
href: 'https://support.metamask.io',
|
|
target: '_blank',
|
|
}, [
|
|
h('span.settings__info-link', 'Visit our Support Center'),
|
|
]),
|
|
]),
|
|
h('div.settings__info-link-item', [
|
|
h('a', {
|
|
href: 'https://metamask.io/',
|
|
target: '_blank',
|
|
}, [
|
|
h('span.settings__info-link', 'Visit our web site'),
|
|
]),
|
|
]),
|
|
h('div.settings__info-link-item', [
|
|
h('a', {
|
|
target: '_blank',
|
|
href: 'mailto:help@metamask.io?subject=Feedback',
|
|
}, [
|
|
h('span.settings__info-link', 'Email us!'),
|
|
]),
|
|
]),
|
|
])
|
|
)
|
|
}
|
|
|
|
renderInfoContent () {
|
|
return (
|
|
h('div.settings__content', [
|
|
h('div.settings__content-row', [
|
|
h('div.settings__content-item.settings__content-item--without-height', [
|
|
this.renderLogo(),
|
|
h('div.settings__info-item', [
|
|
h('div.settings__info-version-header', 'MetaMask Version'),
|
|
h('div.settings__info-version-number', '4.0.0'),
|
|
]),
|
|
h('div.settings__info-item', [
|
|
h(
|
|
'div.settings__info-about',
|
|
'MetaMask is designed and built in California.'
|
|
),
|
|
]),
|
|
]),
|
|
this.renderInfoLinks(),
|
|
]),
|
|
])
|
|
)
|
|
}
|
|
|
|
render () {
|
|
const { goHome } = this.props
|
|
const { activeTab } = this.state
|
|
|
|
return (
|
|
h('.main-container.settings', {}, [
|
|
h('.settings__header', [
|
|
h('div.settings__close-button', {
|
|
onClick: goHome,
|
|
}),
|
|
this.renderTabs(),
|
|
]),
|
|
|
|
activeTab === 'settings'
|
|
? this.renderSettingsContent()
|
|
: this.renderInfoContent(),
|
|
])
|
|
)
|
|
}
|
|
}
|
|
|
|
Settings.propTypes = {
|
|
tab: PropTypes.string,
|
|
metamask: PropTypes.object,
|
|
setCurrentCurrency: PropTypes.func,
|
|
setRpcTarget: PropTypes.func,
|
|
displayWarning: PropTypes.func,
|
|
revealSeedConfirmation: PropTypes.func,
|
|
warning: PropTypes.string,
|
|
goHome: PropTypes.func,
|
|
}
|
|
|
|
const mapStateToProps = state => {
|
|
return {
|
|
metamask: state.metamask,
|
|
warning: state.appState.warning,
|
|
}
|
|
}
|
|
|
|
const mapDispatchToProps = dispatch => {
|
|
return {
|
|
goHome: () => dispatch(actions.goHome()),
|
|
setCurrentCurrency: currency => dispatch(actions.setCurrentCurrency(currency)),
|
|
setRpcTarget: newRpc => dispatch(actions.setRpcTarget(newRpc)),
|
|
displayWarning: warning => dispatch(actions.displayWarning(warning)),
|
|
revealSeedConfirmation: () => dispatch(actions.revealSeedConfirmation()),
|
|
}
|
|
}
|
|
|
|
module.exports = connect(mapStateToProps, mapDispatchToProps)(Settings)
|
|
|