mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 01:39:44 +01:00
Add react-router to allow use of the browser back button
This commit is contained in:
parent
339eb7d1a6
commit
e226b10a89
@ -3,7 +3,8 @@ module.exports = function isPopupOrNotification () {
|
|||||||
// if (url.match(/popup.html$/) || url.match(/home.html$/)) {
|
// if (url.match(/popup.html$/) || url.match(/home.html$/)) {
|
||||||
// Below regexes needed for feature toggles (e.g. see line ~340 in ui/app/app.js)
|
// Below regexes needed for feature toggles (e.g. see line ~340 in ui/app/app.js)
|
||||||
// Revert below regexes to above commented out regexes before merge to master
|
// Revert below regexes to above commented out regexes before merge to master
|
||||||
if (url.match(/popup.html(?:\?.+)*$/) || url.match(/home.html(?:\?.+)*$/)) {
|
if (url.match(/popup.html(?:\?.+)*$/) ||
|
||||||
|
url.match(/home.html(?:\?.+)*$/) || url.match(/home.html(?:#.*)*$/)) {
|
||||||
return 'popup'
|
return 'popup'
|
||||||
} else {
|
} else {
|
||||||
return 'notification'
|
return 'notification'
|
||||||
|
@ -145,6 +145,7 @@
|
|||||||
"react-hyperscript": "^3.0.0",
|
"react-hyperscript": "^3.0.0",
|
||||||
"react-markdown": "^3.0.0",
|
"react-markdown": "^3.0.0",
|
||||||
"react-redux": "^5.0.5",
|
"react-redux": "^5.0.5",
|
||||||
|
"react-router-dom": "^4.2.2",
|
||||||
"react-select": "^1.0.0",
|
"react-select": "^1.0.0",
|
||||||
"react-simple-file-input": "^2.0.0",
|
"react-simple-file-input": "^2.0.0",
|
||||||
"react-toggle-button": "^2.2.0",
|
"react-toggle-button": "^2.2.0",
|
||||||
|
@ -71,8 +71,8 @@ AccountDetailScreen.prototype.tabSections = function () {
|
|||||||
{ content: 'Sent', key: 'history' },
|
{ content: 'Sent', key: 'history' },
|
||||||
{ content: 'Tokens', key: 'tokens' },
|
{ content: 'Tokens', key: 'tokens' },
|
||||||
],
|
],
|
||||||
defaultTab: currentAccountTab || 'history',
|
selectedTab: currentAccountTab || 'history',
|
||||||
tabSelected: (key) => {
|
onSelect: key => {
|
||||||
this.props.dispatch(actions.setCurrentAccountTab(key))
|
this.props.dispatch(actions.setCurrentAccountTab(key))
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
@ -266,14 +266,18 @@ function tryUnlockMetamask (password) {
|
|||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
dispatch(actions.unlockInProgress())
|
dispatch(actions.unlockInProgress())
|
||||||
log.debug(`background.submitPassword`)
|
log.debug(`background.submitPassword`)
|
||||||
background.submitPassword(password, (err) => {
|
|
||||||
dispatch(actions.hideLoadingIndication())
|
return new Promise((resolve, reject) => {
|
||||||
if (err) {
|
background.submitPassword(password, err => {
|
||||||
dispatch(actions.unlockFailed(err.message))
|
dispatch(actions.hideLoadingIndication())
|
||||||
} else {
|
|
||||||
dispatch(actions.transitionForward())
|
if (err) {
|
||||||
forceUpdateMetamaskState(dispatch)
|
reject(err)
|
||||||
}
|
} else {
|
||||||
|
dispatch(actions.transitionForward())
|
||||||
|
return forceUpdateMetamaskState(dispatch).then(resolve)
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -291,7 +295,7 @@ function transitionBackward () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function confirmSeedWords () {
|
function confirmSeedWords () {
|
||||||
return (dispatch) => {
|
return dispatch => {
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
log.debug(`background.clearSeedWordCache`)
|
log.debug(`background.clearSeedWordCache`)
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -299,7 +303,7 @@ function confirmSeedWords () {
|
|||||||
dispatch(actions.hideLoadingIndication())
|
dispatch(actions.hideLoadingIndication())
|
||||||
if (err) {
|
if (err) {
|
||||||
dispatch(actions.displayWarning(err.message))
|
dispatch(actions.displayWarning(err.message))
|
||||||
reject(err)
|
return reject(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info('Seed word cache cleared. ' + account)
|
log.info('Seed word cache cleared. ' + account)
|
||||||
@ -344,14 +348,14 @@ function createNewVaultAndKeychain (password) {
|
|||||||
return reject(err)
|
return reject(err)
|
||||||
}
|
}
|
||||||
log.debug(`background.placeSeedWords`)
|
log.debug(`background.placeSeedWords`)
|
||||||
|
|
||||||
background.placeSeedWords((err) => {
|
background.placeSeedWords((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
dispatch(actions.displayWarning(err.message))
|
dispatch(actions.displayWarning(err.message))
|
||||||
return reject(err)
|
return reject(err)
|
||||||
}
|
}
|
||||||
dispatch(actions.hideLoadingIndication())
|
dispatch(actions.hideLoadingIndication())
|
||||||
forceUpdateMetamaskState(dispatch)
|
forceUpdateMetamaskState(dispatch).then(resolve)
|
||||||
resolve()
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -696,16 +700,23 @@ function updateAndApproveTx (txData) {
|
|||||||
log.info('actions: updateAndApproveTx: ' + JSON.stringify(txData))
|
log.info('actions: updateAndApproveTx: ' + JSON.stringify(txData))
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
log.debug(`actions calling background.updateAndApproveTx`)
|
log.debug(`actions calling background.updateAndApproveTx`)
|
||||||
background.updateAndApproveTransaction(txData, (err) => {
|
|
||||||
dispatch(actions.hideLoadingIndication())
|
return new Promise((resolve, reject) => {
|
||||||
dispatch(actions.updateTransactionParams(txData.id, txData.txParams))
|
background.updateAndApproveTransaction(txData, err => {
|
||||||
dispatch(actions.clearSend())
|
dispatch(actions.hideLoadingIndication())
|
||||||
if (err) {
|
dispatch(actions.updateTransactionParams(txData.id, txData.txParams))
|
||||||
dispatch(actions.txError(err))
|
dispatch(actions.clearSend())
|
||||||
dispatch(actions.goHome())
|
|
||||||
return log.error(err.message)
|
if (err) {
|
||||||
}
|
dispatch(actions.txError(err))
|
||||||
dispatch(actions.completedTx(txData.id))
|
dispatch(actions.goHome())
|
||||||
|
log.error(err.message)
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(actions.completedTx(txData.id))
|
||||||
|
resolve(txData)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -751,10 +762,13 @@ function cancelTypedMsg (msgData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cancelTx (txData) {
|
function cancelTx (txData) {
|
||||||
return (dispatch) => {
|
return dispatch => {
|
||||||
log.debug(`background.cancelTransaction`)
|
log.debug(`background.cancelTransaction`)
|
||||||
background.cancelTransaction(txData.id, () => {
|
return new Promise((resolve, reject) => {
|
||||||
dispatch(actions.completedTx(txData.id))
|
background.cancelTransaction(txData.id, () => {
|
||||||
|
dispatch(actions.completedTx(txData.id))
|
||||||
|
resolve(txData)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1585,11 +1599,17 @@ function callBackgroundThenUpdate (method, ...args) {
|
|||||||
|
|
||||||
function forceUpdateMetamaskState (dispatch) {
|
function forceUpdateMetamaskState (dispatch) {
|
||||||
log.debug(`background.getState`)
|
log.debug(`background.getState`)
|
||||||
background.getState((err, newState) => {
|
|
||||||
if (err) {
|
return new Promise((resolve, reject) => {
|
||||||
return dispatch(actions.displayWarning(err.message))
|
background.getState((err, newState) => {
|
||||||
}
|
if (err) {
|
||||||
dispatch(actions.updateMetamaskState(newState))
|
reject(err)
|
||||||
|
return dispatch(actions.displayWarning(err.message))
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(actions.updateMetamaskState(newState))
|
||||||
|
resolve(newState)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
966
ui/app/app.js
966
ui/app/app.js
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,19 @@
|
|||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
const Component = require('react').Component
|
const Component = require('react').Component
|
||||||
const connect = require('react-redux').connect
|
const connect = require('react-redux').connect
|
||||||
|
const { compose } = require('recompose')
|
||||||
|
const { withRouter } = require('react-router-dom')
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const actions = require('../../actions')
|
const actions = require('../../actions')
|
||||||
const { Menu, Item, Divider, CloseArea } = require('../dropdowns/components/menu')
|
const { Menu, Item, Divider, CloseArea } = require('../dropdowns/components/menu')
|
||||||
const Identicon = require('../identicon')
|
const Identicon = require('../identicon')
|
||||||
const { formatBalance } = require('../../util')
|
const { formatBalance } = require('../../util')
|
||||||
|
const { SETTINGS_ROUTE, INFO_ROUTE, IMPORT_ACCOUNT_ROUTE } = require('../../routes')
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountMenu)
|
module.exports = compose(
|
||||||
|
withRouter,
|
||||||
|
connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
)(AccountMenu)
|
||||||
|
|
||||||
inherits(AccountMenu, Component)
|
inherits(AccountMenu, Component)
|
||||||
function AccountMenu () { Component.call(this) }
|
function AccountMenu () { Component.call(this) }
|
||||||
@ -19,7 +25,6 @@ function mapStateToProps (state) {
|
|||||||
keyrings: state.metamask.keyrings,
|
keyrings: state.metamask.keyrings,
|
||||||
identities: state.metamask.identities,
|
identities: state.metamask.identities,
|
||||||
accounts: state.metamask.accounts,
|
accounts: state.metamask.accounts,
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +68,7 @@ AccountMenu.prototype.render = function () {
|
|||||||
lockMetamask,
|
lockMetamask,
|
||||||
showConfigPage,
|
showConfigPage,
|
||||||
showInfoPage,
|
showInfoPage,
|
||||||
|
history,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
return h(Menu, { className: 'account-menu', isShowing: isAccountMenuOpen }, [
|
return h(Menu, { className: 'account-menu', isShowing: isAccountMenuOpen }, [
|
||||||
@ -84,18 +90,27 @@ AccountMenu.prototype.render = function () {
|
|||||||
text: 'Create Account',
|
text: 'Create Account',
|
||||||
}),
|
}),
|
||||||
h(Item, {
|
h(Item, {
|
||||||
onClick: showImportPage,
|
onClick: () => {
|
||||||
|
toggleAccountMenu()
|
||||||
|
history.push(IMPORT_ACCOUNT_ROUTE)
|
||||||
|
},
|
||||||
icon: h('img', { src: 'images/import-account.svg' }),
|
icon: h('img', { src: 'images/import-account.svg' }),
|
||||||
text: 'Import Account',
|
text: 'Import Account',
|
||||||
}),
|
}),
|
||||||
h(Divider),
|
h(Divider),
|
||||||
h(Item, {
|
h(Item, {
|
||||||
onClick: showInfoPage,
|
onClick: () => {
|
||||||
|
toggleAccountMenu()
|
||||||
|
history.push(INFO_ROUTE)
|
||||||
|
},
|
||||||
icon: h('img', { src: 'images/mm-info-icon.svg' }),
|
icon: h('img', { src: 'images/mm-info-icon.svg' }),
|
||||||
text: 'Info & Help',
|
text: 'Info & Help',
|
||||||
}),
|
}),
|
||||||
h(Item, {
|
h(Item, {
|
||||||
onClick: showConfigPage,
|
onClick: () => {
|
||||||
|
toggleAccountMenu()
|
||||||
|
history.push(SETTINGS_ROUTE)
|
||||||
|
},
|
||||||
icon: h('img', { src: 'images/settings.svg' }),
|
icon: h('img', { src: 'images/settings.svg' }),
|
||||||
text: 'Settings',
|
text: 'Settings',
|
||||||
}),
|
}),
|
||||||
|
@ -1,132 +0,0 @@
|
|||||||
const inherits = require('util').inherits
|
|
||||||
const Component = require('react').Component
|
|
||||||
const h = require('react-hyperscript')
|
|
||||||
const ReactMarkdown = require('react-markdown')
|
|
||||||
const linker = require('extension-link-enabler')
|
|
||||||
const findDOMNode = require('react-dom').findDOMNode
|
|
||||||
|
|
||||||
module.exports = Notice
|
|
||||||
|
|
||||||
inherits(Notice, Component)
|
|
||||||
function Notice () {
|
|
||||||
Component.call(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
Notice.prototype.render = function () {
|
|
||||||
const { notice, onConfirm } = this.props
|
|
||||||
const { title, date, body } = notice
|
|
||||||
const state = this.state || { disclaimerDisabled: true }
|
|
||||||
const disabled = state.disclaimerDisabled
|
|
||||||
|
|
||||||
return (
|
|
||||||
h('.flex-column.flex-center.flex-grow', {
|
|
||||||
style: {
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
}, [
|
|
||||||
h('h3.flex-center.text-transform-uppercase.terms-header', {
|
|
||||||
style: {
|
|
||||||
background: '#EBEBEB',
|
|
||||||
color: '#AEAEAE',
|
|
||||||
width: '100%',
|
|
||||||
fontSize: '20px',
|
|
||||||
textAlign: 'center',
|
|
||||||
padding: 6,
|
|
||||||
},
|
|
||||||
}, [
|
|
||||||
title,
|
|
||||||
]),
|
|
||||||
|
|
||||||
h('h5.flex-center.text-transform-uppercase.terms-header', {
|
|
||||||
style: {
|
|
||||||
background: '#EBEBEB',
|
|
||||||
color: '#AEAEAE',
|
|
||||||
marginBottom: 24,
|
|
||||||
width: '100%',
|
|
||||||
fontSize: '20px',
|
|
||||||
textAlign: 'center',
|
|
||||||
padding: 6,
|
|
||||||
},
|
|
||||||
}, [
|
|
||||||
date,
|
|
||||||
]),
|
|
||||||
|
|
||||||
h('style', `
|
|
||||||
|
|
||||||
.markdown {
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.markdown h1, .markdown h2, .markdown h3 {
|
|
||||||
margin: 10px 0;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.markdown strong {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.markdown em {
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.markdown p {
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.markdown a {
|
|
||||||
color: #df6b0e;
|
|
||||||
}
|
|
||||||
|
|
||||||
`),
|
|
||||||
|
|
||||||
h('div.markdown', {
|
|
||||||
onScroll: (e) => {
|
|
||||||
var object = e.currentTarget
|
|
||||||
if (object.offsetHeight + object.scrollTop + 100 >= object.scrollHeight) {
|
|
||||||
this.setState({disclaimerDisabled: false})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
background: 'rgb(235, 235, 235)',
|
|
||||||
height: '310px',
|
|
||||||
padding: '6px',
|
|
||||||
width: '90%',
|
|
||||||
overflowY: 'scroll',
|
|
||||||
scroll: 'auto',
|
|
||||||
},
|
|
||||||
}, [
|
|
||||||
h(ReactMarkdown, {
|
|
||||||
className: 'notice-box',
|
|
||||||
source: body,
|
|
||||||
skipHtml: true,
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
|
|
||||||
h('button.primary', {
|
|
||||||
disabled,
|
|
||||||
onClick: () => {
|
|
||||||
this.setState({disclaimerDisabled: true})
|
|
||||||
onConfirm()
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
marginTop: '18px',
|
|
||||||
},
|
|
||||||
}, 'Accept'),
|
|
||||||
])
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
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})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Notice.prototype.componentWillUnmount = function () {
|
|
||||||
// eslint-disable-next-line react/no-find-dom-node
|
|
||||||
var node = findDOMNode(this)
|
|
||||||
linker.teardownListener(node)
|
|
||||||
}
|
|
@ -5,8 +5,8 @@ const h = require('react-hyperscript')
|
|||||||
const connect = require('react-redux').connect
|
const connect = require('react-redux').connect
|
||||||
const Fuse = require('fuse.js')
|
const Fuse = require('fuse.js')
|
||||||
const contractMap = require('eth-contract-metadata')
|
const contractMap = require('eth-contract-metadata')
|
||||||
const TokenBalance = require('./components/token-balance')
|
const TokenBalance = require('../../components/token-balance')
|
||||||
const Identicon = require('./components/identicon')
|
const Identicon = require('../../components/identicon')
|
||||||
const contractList = Object.entries(contractMap)
|
const contractList = Object.entries(contractMap)
|
||||||
.map(([ _, tokenData]) => tokenData)
|
.map(([ _, tokenData]) => tokenData)
|
||||||
.filter(tokenData => Boolean(tokenData.erc20))
|
.filter(tokenData => Boolean(tokenData.erc20))
|
||||||
@ -19,10 +19,12 @@ const fuse = new Fuse(contractList, {
|
|||||||
minMatchCharLength: 1,
|
minMatchCharLength: 1,
|
||||||
keys: ['address', 'name', 'symbol'],
|
keys: ['address', 'name', 'symbol'],
|
||||||
})
|
})
|
||||||
const actions = require('./actions')
|
// const actions = require('./actions')
|
||||||
|
const actions = require('../../actions')
|
||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
const { tokenInfoGetter } = require('./token-util')
|
const { tokenInfoGetter } = require('../../token-util')
|
||||||
const R = require('ramda')
|
const R = require('ramda')
|
||||||
|
const { DEFAULT_ROUTE } = require('../../routes')
|
||||||
|
|
||||||
const emptyAddr = '0x0000000000000000000000000000000000000000'
|
const emptyAddr = '0x0000000000000000000000000000000000000000'
|
||||||
|
|
||||||
@ -258,7 +260,7 @@ AddTokenScreen.prototype.renderConfirmation = function () {
|
|||||||
selectedTokens,
|
selectedTokens,
|
||||||
} = this.state
|
} = this.state
|
||||||
|
|
||||||
const { addTokens, goHome } = this.props
|
const { addTokens, history } = this.props
|
||||||
|
|
||||||
const customToken = {
|
const customToken = {
|
||||||
address,
|
address,
|
||||||
@ -296,7 +298,7 @@ AddTokenScreen.prototype.renderConfirmation = function () {
|
|||||||
]),
|
]),
|
||||||
h('div.add-token__buttons', [
|
h('div.add-token__buttons', [
|
||||||
h('button.btn-secondary', {
|
h('button.btn-secondary', {
|
||||||
onClick: () => addTokens(tokens).then(goHome),
|
onClick: () => addTokens(tokens).then(() => history.push(DEFAULT_ROUTE)),
|
||||||
}, 'Add Tokens'),
|
}, 'Add Tokens'),
|
||||||
h('button.btn-tertiary', {
|
h('button.btn-tertiary', {
|
||||||
onClick: () => this.setState({ isShowingConfirmation: false }),
|
onClick: () => this.setState({ isShowingConfirmation: false }),
|
||||||
@ -308,7 +310,7 @@ AddTokenScreen.prototype.renderConfirmation = function () {
|
|||||||
|
|
||||||
AddTokenScreen.prototype.render = function () {
|
AddTokenScreen.prototype.render = function () {
|
||||||
const { isCollapsed, errors, isShowingConfirmation } = this.state
|
const { isCollapsed, errors, isShowingConfirmation } = this.state
|
||||||
const { goHome } = this.props
|
const { history } = this.props
|
||||||
|
|
||||||
return isShowingConfirmation
|
return isShowingConfirmation
|
||||||
? this.renderConfirmation()
|
? this.renderConfirmation()
|
||||||
@ -349,7 +351,7 @@ AddTokenScreen.prototype.render = function () {
|
|||||||
onClick: this.onNext,
|
onClick: this.onNext,
|
||||||
}, 'Next'),
|
}, 'Next'),
|
||||||
h('button.btn-tertiary', {
|
h('button.btn-tertiary', {
|
||||||
onClick: goHome,
|
onClick: () => history.goBack(),
|
||||||
}, 'Cancel'),
|
}, 'Cancel'),
|
||||||
]),
|
]),
|
||||||
])
|
])
|
42
ui/app/components/pages/authenticated.js
Normal file
42
ui/app/components/pages/authenticated.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
const { connect } = require('react-redux')
|
||||||
|
const PropTypes = require('prop-types')
|
||||||
|
const { Redirect, Route } = require('react-router-dom')
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const { UNLOCK_ROUTE, INITIALIZE_MENU_ROUTE } = require('../../routes')
|
||||||
|
|
||||||
|
const Authenticated = ({ component: Component, isUnlocked, isInitialized, ...props }) => {
|
||||||
|
|
||||||
|
const render = props => {
|
||||||
|
switch (true) {
|
||||||
|
case isUnlocked:
|
||||||
|
return h(Component, { ...props })
|
||||||
|
case !isInitialized:
|
||||||
|
return h(Redirect, { to: { pathname: INITIALIZE_MENU_ROUTE } })
|
||||||
|
default:
|
||||||
|
return h(Redirect, { to: { pathname: UNLOCK_ROUTE } })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
h(Route, {
|
||||||
|
...props,
|
||||||
|
render,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Authenticated.propTypes = {
|
||||||
|
component: PropTypes.func,
|
||||||
|
isUnlocked: PropTypes.bool,
|
||||||
|
isInitialized: PropTypes.bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
const { metamask: { isUnlocked, isInitialized } } = state
|
||||||
|
return {
|
||||||
|
isUnlocked,
|
||||||
|
isInitialized,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = connect(mapStateToProps)(Authenticated)
|
95
ui/app/components/pages/import-account/index.js
Normal file
95
ui/app/components/pages/import-account/index.js
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
const Component = require('react').Component
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const PropTypes = require('prop-types')
|
||||||
|
import Select from 'react-select'
|
||||||
|
|
||||||
|
// Subviews
|
||||||
|
const JsonImportView = require('./json.js')
|
||||||
|
const PrivateKeyImportView = require('./private-key.js')
|
||||||
|
|
||||||
|
const PRIVATE_KEY_MENU_ITEM = 'Private Key'
|
||||||
|
const JSON_FILE_MENU_ITEM = 'JSON File'
|
||||||
|
|
||||||
|
class ImportAccount extends Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
current: PRIVATE_KEY_MENU_ITEM,
|
||||||
|
menuItems: [ PRIVATE_KEY_MENU_ITEM, JSON_FILE_MENU_ITEM ],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderImportView () {
|
||||||
|
const { current } = this.state
|
||||||
|
|
||||||
|
switch (current) {
|
||||||
|
case 'Private Key':
|
||||||
|
return h(PrivateKeyImportView)
|
||||||
|
case 'JSON File':
|
||||||
|
return h(JsonImportView)
|
||||||
|
default:
|
||||||
|
return h(JsonImportView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { history } = this.props
|
||||||
|
const { current, menuItems } = this.state
|
||||||
|
|
||||||
|
return (
|
||||||
|
h('div.flex-center', {
|
||||||
|
style: {
|
||||||
|
flexDirection: 'column',
|
||||||
|
marginTop: '32px',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('.section-title.flex-row.flex-center', [
|
||||||
|
h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', {
|
||||||
|
onClick: history.goBack,
|
||||||
|
}),
|
||||||
|
h('h2.page-subtitle', 'Import Accounts'),
|
||||||
|
]),
|
||||||
|
h('div', {
|
||||||
|
style: {
|
||||||
|
padding: '10px 0',
|
||||||
|
width: '260px',
|
||||||
|
color: 'rgb(174, 174, 174)',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
|
||||||
|
h('h3', { style: { padding: '3px' } }, 'SELECT TYPE'),
|
||||||
|
|
||||||
|
h('style', `
|
||||||
|
.has-value.Select--single > .Select-control .Select-value .Select-value-label, .Select-value-label {
|
||||||
|
color: rgb(174,174,174);
|
||||||
|
}
|
||||||
|
`),
|
||||||
|
|
||||||
|
h(Select, {
|
||||||
|
name: 'import-type-select',
|
||||||
|
clearable: false,
|
||||||
|
value: current,
|
||||||
|
options: menuItems.map(type => {
|
||||||
|
return {
|
||||||
|
value: type,
|
||||||
|
label: type,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
onChange: opt => {
|
||||||
|
this.setState({ current: opt.value })
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
|
||||||
|
this.renderImportView(),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImportAccount.propTypes = {
|
||||||
|
history: PropTypes.object,
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ImportAccount
|
@ -2,7 +2,7 @@ const inherits = require('util').inherits
|
|||||||
const Component = require('react').Component
|
const Component = require('react').Component
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const connect = require('react-redux').connect
|
const connect = require('react-redux').connect
|
||||||
const actions = require('../../actions')
|
const actions = require('../../../actions')
|
||||||
const FileInput = require('react-simple-file-input').default
|
const FileInput = require('react-simple-file-input').default
|
||||||
|
|
||||||
const HELP_LINK = 'https://support.metamask.io/kb/article/7-importing-accounts'
|
const HELP_LINK = 'https://support.metamask.io/kb/article/7-importing-accounts'
|
@ -2,7 +2,7 @@ const inherits = require('util').inherits
|
|||||||
const Component = require('react').Component
|
const Component = require('react').Component
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const connect = require('react-redux').connect
|
const connect = require('react-redux').connect
|
||||||
const actions = require('../../actions')
|
const actions = require('../../../actions')
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps)(PrivateKeyImportView)
|
module.exports = connect(mapStateToProps)(PrivateKeyImportView)
|
||||||
|
|
167
ui/app/components/pages/keychains/restore-vault.js
Normal file
167
ui/app/components/pages/keychains/restore-vault.js
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
const { withRouter } = require('react-router-dom')
|
||||||
|
const PropTypes = require('prop-types')
|
||||||
|
const { compose } = require('recompose')
|
||||||
|
const PersistentForm = require('../../../../lib/persistent-form')
|
||||||
|
const { connect } = require('react-redux')
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const { createNewVaultAndRestore } = require('../../../actions')
|
||||||
|
const { DEFAULT_ROUTE } = require('../../../routes')
|
||||||
|
|
||||||
|
class RestoreVaultPage extends PersistentForm {
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
error: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createOnEnter (event) {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
this.createNewVaultAndRestore()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createNewVaultAndRestore () {
|
||||||
|
this.setState({ error: null })
|
||||||
|
|
||||||
|
// check password
|
||||||
|
var passwordBox = document.getElementById('password-box')
|
||||||
|
var password = passwordBox.value
|
||||||
|
var passwordConfirmBox = document.getElementById('password-box-confirm')
|
||||||
|
var passwordConfirm = passwordConfirmBox.value
|
||||||
|
|
||||||
|
if (password.length < 8) {
|
||||||
|
this.setState({ error: 'Password not long enough' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (password !== passwordConfirm) {
|
||||||
|
this.setState({ error: 'Passwords don\'t match' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// check seed
|
||||||
|
var seedBox = document.querySelector('textarea.twelve-word-phrase')
|
||||||
|
var seed = seedBox.value.trim()
|
||||||
|
if (seed.split(' ').length !== 12) {
|
||||||
|
this.setState({ error: 'Seed phrases are 12 words long' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// submit
|
||||||
|
this.props.createNewVaultAndRestore(password, seed)
|
||||||
|
.then(() => history.push(DEFAULT_ROUTE))
|
||||||
|
.catch(({ message }) => this.setState({ error: message }))
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { error } = this.state
|
||||||
|
const { history } = this.props
|
||||||
|
this.persistentFormParentId = 'restore-vault-form'
|
||||||
|
|
||||||
|
return (
|
||||||
|
h('.initialize-screen.flex-column.flex-center.flex-grow', [
|
||||||
|
|
||||||
|
h('h3.flex-center.text-transform-uppercase', {
|
||||||
|
style: {
|
||||||
|
background: '#EBEBEB',
|
||||||
|
color: '#AEAEAE',
|
||||||
|
marginBottom: 24,
|
||||||
|
width: '100%',
|
||||||
|
fontSize: '20px',
|
||||||
|
padding: 6,
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
'Restore Vault',
|
||||||
|
]),
|
||||||
|
|
||||||
|
// wallet seed entry
|
||||||
|
h('h3', 'Wallet Seed'),
|
||||||
|
h('textarea.twelve-word-phrase.letter-spacey', {
|
||||||
|
dataset: {
|
||||||
|
persistentFormId: 'wallet-seed',
|
||||||
|
},
|
||||||
|
placeholder: 'Enter your secret twelve word phrase here to restore your vault.',
|
||||||
|
}),
|
||||||
|
|
||||||
|
// password
|
||||||
|
h('input.large-input.letter-spacey', {
|
||||||
|
type: 'password',
|
||||||
|
id: 'password-box',
|
||||||
|
placeholder: 'New Password (min 8 chars)',
|
||||||
|
dataset: {
|
||||||
|
persistentFormId: 'password',
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
width: 260,
|
||||||
|
marginTop: 12,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
// confirm password
|
||||||
|
h('input.large-input.letter-spacey', {
|
||||||
|
type: 'password',
|
||||||
|
id: 'password-box-confirm',
|
||||||
|
placeholder: 'Confirm Password',
|
||||||
|
onKeyPress: this.createOnEnter.bind(this),
|
||||||
|
dataset: {
|
||||||
|
persistentFormId: 'password-confirmation',
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
width: 260,
|
||||||
|
marginTop: 16,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
error && (
|
||||||
|
h('span.error.in-progress-notification', error)
|
||||||
|
),
|
||||||
|
|
||||||
|
// submit
|
||||||
|
h('.flex-row.flex-space-between', {
|
||||||
|
style: {
|
||||||
|
marginTop: 30,
|
||||||
|
width: '50%',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
|
||||||
|
// cancel
|
||||||
|
h('button.primary', { onClick: () => history.goBack() }, 'CANCEL'),
|
||||||
|
|
||||||
|
// submit
|
||||||
|
h('button.primary', {
|
||||||
|
onClick: this.createNewVaultAndRestore.bind(this),
|
||||||
|
}, 'OK'),
|
||||||
|
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RestoreVaultPage.propTypes = {
|
||||||
|
history: PropTypes.object,
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
const { appState: { warning, forgottenPassword } } = state
|
||||||
|
|
||||||
|
return {
|
||||||
|
warning,
|
||||||
|
forgottenPassword,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
createNewVaultAndRestore: (password, seed) => {
|
||||||
|
return dispatch(createNewVaultAndRestore(password, seed))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = compose(
|
||||||
|
withRouter,
|
||||||
|
connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
)(RestoreVaultPage)
|
192
ui/app/components/pages/keychains/reveal-seed.js
Normal file
192
ui/app/components/pages/keychains/reveal-seed.js
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
const { Component } = require('react')
|
||||||
|
const { connect } = require('react-redux')
|
||||||
|
const PropTypes = require('prop-types')
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const { exportAsFile } = require('../../../util')
|
||||||
|
const { requestRevealSeed, confirmSeedWords } = require('../../../actions')
|
||||||
|
const { DEFAULT_ROUTE } = require('../../../routes')
|
||||||
|
|
||||||
|
class RevealSeedPage extends Component {
|
||||||
|
componentDidMount () {
|
||||||
|
document.getElementById('password-box').focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
checkConfirmation (event) {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
event.preventDefault()
|
||||||
|
this.revealSeedWords()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
revealSeedWords () {
|
||||||
|
const password = document.getElementById('password-box').value
|
||||||
|
this.props.requestRevealSeed(password)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSeed () {
|
||||||
|
const { seedWords, confirmSeedWords, history } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
h('.initialize-screen.flex-column.flex-center.flex-grow', [
|
||||||
|
|
||||||
|
h('h3.flex-center.text-transform-uppercase', {
|
||||||
|
style: {
|
||||||
|
background: '#EBEBEB',
|
||||||
|
color: '#AEAEAE',
|
||||||
|
marginTop: 36,
|
||||||
|
marginBottom: 8,
|
||||||
|
width: '100%',
|
||||||
|
fontSize: '20px',
|
||||||
|
padding: 6,
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
'Vault Created',
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('div', {
|
||||||
|
style: {
|
||||||
|
fontSize: '1em',
|
||||||
|
marginTop: '10px',
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('span.error', 'These 12 words are the only way to restore your MetaMask accounts.\nSave them somewhere safe and secret.'),
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('textarea.twelve-word-phrase', {
|
||||||
|
readOnly: true,
|
||||||
|
value: seedWords,
|
||||||
|
}),
|
||||||
|
|
||||||
|
h('button.primary', {
|
||||||
|
onClick: () => confirmSeedWords().then(() => history.push(DEFAULT_ROUTE)),
|
||||||
|
style: {
|
||||||
|
margin: '24px',
|
||||||
|
fontSize: '0.9em',
|
||||||
|
marginBottom: '10px',
|
||||||
|
},
|
||||||
|
}, 'I\'ve copied it somewhere safe'),
|
||||||
|
|
||||||
|
h('button.primary', {
|
||||||
|
onClick: () => exportAsFile(`MetaMask Seed Words`, seedWords),
|
||||||
|
style: {
|
||||||
|
margin: '10px',
|
||||||
|
fontSize: '0.9em',
|
||||||
|
},
|
||||||
|
}, 'Save Seed Words As File'),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderConfirmation () {
|
||||||
|
const { history, warning, inProgress } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
h('.initialize-screen.flex-column.flex-center.flex-grow', {
|
||||||
|
style: { maxWidth: '420px' },
|
||||||
|
}, [
|
||||||
|
|
||||||
|
h('h3.flex-center.text-transform-uppercase', {
|
||||||
|
style: {
|
||||||
|
background: '#EBEBEB',
|
||||||
|
color: '#AEAEAE',
|
||||||
|
marginBottom: 24,
|
||||||
|
width: '100%',
|
||||||
|
fontSize: '20px',
|
||||||
|
padding: 6,
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
'Reveal Seed Words',
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('.div', {
|
||||||
|
style: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
padding: '20px',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
|
||||||
|
h('h4', 'Do not recover your seed words in a public place! These words can be used to steal all your accounts.'),
|
||||||
|
|
||||||
|
// confirmation
|
||||||
|
h('input.large-input.letter-spacey', {
|
||||||
|
type: 'password',
|
||||||
|
id: 'password-box',
|
||||||
|
placeholder: 'Enter your password to confirm',
|
||||||
|
onKeyPress: this.checkConfirmation.bind(this),
|
||||||
|
style: {
|
||||||
|
width: 260,
|
||||||
|
marginTop: '12px',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
h('.flex-row.flex-start', {
|
||||||
|
style: {
|
||||||
|
marginTop: 30,
|
||||||
|
width: '50%',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
// cancel
|
||||||
|
h('button.primary', {
|
||||||
|
onClick: () => history.goBack(),
|
||||||
|
}, 'CANCEL'),
|
||||||
|
|
||||||
|
// submit
|
||||||
|
h('button.primary', {
|
||||||
|
style: { marginLeft: '10px' },
|
||||||
|
onClick: this.revealSeedWords.bind(this),
|
||||||
|
}, 'OK'),
|
||||||
|
|
||||||
|
]),
|
||||||
|
|
||||||
|
warning && (
|
||||||
|
h('span.error', {
|
||||||
|
style: {
|
||||||
|
margin: '20px',
|
||||||
|
},
|
||||||
|
}, warning.split('-'))
|
||||||
|
),
|
||||||
|
|
||||||
|
inProgress && (
|
||||||
|
h('span.in-progress-notification', 'Generating Seed...')
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
return this.props.seedWords
|
||||||
|
? this.renderSeed()
|
||||||
|
: this.renderConfirmation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RevealSeedPage.propTypes = {
|
||||||
|
requestRevealSeed: PropTypes.func,
|
||||||
|
confirmSeedWords: PropTypes.func,
|
||||||
|
seedWords: PropTypes.string,
|
||||||
|
inProgress: PropTypes.bool,
|
||||||
|
history: PropTypes.object,
|
||||||
|
warning: PropTypes.string,
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
const { appState: { warning }, metamask: { seedWords } } = state
|
||||||
|
|
||||||
|
return {
|
||||||
|
warning,
|
||||||
|
seedWords,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
requestRevealSeed: password => dispatch(requestRevealSeed(password)),
|
||||||
|
confirmSeedWords: () => dispatch(confirmSeedWords()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = connect(mapStateToProps, mapDispatchToProps)(RevealSeedPage)
|
219
ui/app/components/pages/notice.js
Normal file
219
ui/app/components/pages/notice.js
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
const { Component } = require('react')
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const { connect } = require('react-redux')
|
||||||
|
const PropTypes = require('prop-types')
|
||||||
|
const ReactMarkdown = require('react-markdown')
|
||||||
|
const linker = require('extension-link-enabler')
|
||||||
|
const generateLostAccountsNotice = require('../../../lib/lost-accounts-notice')
|
||||||
|
const findDOMNode = require('react-dom').findDOMNode
|
||||||
|
const actions = require('../../actions')
|
||||||
|
const { DEFAULT_ROUTE } = require('../../routes')
|
||||||
|
|
||||||
|
class Notice extends Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
disclaimerDisabled: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount () {
|
||||||
|
if (!this.props.notice) {
|
||||||
|
this.props.history.push(DEFAULT_ROUTE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
// 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 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps (nextProps) {
|
||||||
|
if (!nextProps.notice) {
|
||||||
|
this.props.history.push(DEFAULT_ROUTE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount () {
|
||||||
|
// eslint-disable-next-line react/no-find-dom-node
|
||||||
|
var node = findDOMNode(this)
|
||||||
|
linker.teardownListener(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleAccept () {
|
||||||
|
this.setState({ disclaimerDisabled: true })
|
||||||
|
this.props.onConfirm()
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { notice = {} } = this.props
|
||||||
|
const { title, date, body } = notice
|
||||||
|
// const state = this.state || { disclaimerDisabled: true }
|
||||||
|
const { disclaimerDisabled } = this.state
|
||||||
|
|
||||||
|
return (
|
||||||
|
h('.flex-column.flex-center.flex-grow', {
|
||||||
|
style: {
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('h3.flex-center.text-transform-uppercase.terms-header', {
|
||||||
|
style: {
|
||||||
|
background: '#EBEBEB',
|
||||||
|
color: '#AEAEAE',
|
||||||
|
width: '100%',
|
||||||
|
fontSize: '20px',
|
||||||
|
textAlign: 'center',
|
||||||
|
padding: 6,
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
title,
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('h5.flex-center.text-transform-uppercase.terms-header', {
|
||||||
|
style: {
|
||||||
|
background: '#EBEBEB',
|
||||||
|
color: '#AEAEAE',
|
||||||
|
marginBottom: 24,
|
||||||
|
width: '100%',
|
||||||
|
fontSize: '20px',
|
||||||
|
textAlign: 'center',
|
||||||
|
padding: 6,
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
date,
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('style', `
|
||||||
|
|
||||||
|
.markdown {
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h1, .markdown h2, .markdown h3 {
|
||||||
|
margin: 10px 0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown strong {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.markdown em {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown p {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown a {
|
||||||
|
color: #df6b0e;
|
||||||
|
}
|
||||||
|
|
||||||
|
`),
|
||||||
|
|
||||||
|
h('div.markdown', {
|
||||||
|
onScroll: (e) => {
|
||||||
|
var object = e.currentTarget
|
||||||
|
if (object.offsetHeight + object.scrollTop + 100 >= object.scrollHeight) {
|
||||||
|
this.setState({ disclaimerDisabled: false })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
background: 'rgb(235, 235, 235)',
|
||||||
|
height: '310px',
|
||||||
|
padding: '6px',
|
||||||
|
width: '90%',
|
||||||
|
overflowY: 'scroll',
|
||||||
|
scroll: 'auto',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h(ReactMarkdown, {
|
||||||
|
className: 'notice-box',
|
||||||
|
source: body,
|
||||||
|
skipHtml: true,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('button.primary', {
|
||||||
|
disabled: disclaimerDisabled,
|
||||||
|
onClick: () => this.handleAccept(),
|
||||||
|
style: {
|
||||||
|
marginTop: '18px',
|
||||||
|
},
|
||||||
|
}, 'Accept'),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
const { metamask } = state
|
||||||
|
const { noActiveNotices, lastUnreadNotice, lostAccounts } = metamask
|
||||||
|
// if (!props.noActiveNotices) {
|
||||||
|
// log.debug('rendering notice screen for unread notices.')
|
||||||
|
// return h(NoticeScreen, {
|
||||||
|
// notice: props.lastUnreadNotice,
|
||||||
|
// key: 'NoticeScreen',
|
||||||
|
// onConfirm: () => props.dispatch(actions.markNoticeRead(props.lastUnreadNotice)),
|
||||||
|
// })
|
||||||
|
// } else if (props.lostAccounts && props.lostAccounts.length > 0) {
|
||||||
|
// log.debug('rendering notice screen for lost accounts view.')
|
||||||
|
// return h(NoticeScreen, {
|
||||||
|
// notice: generateLostAccountsNotice(props.lostAccounts),
|
||||||
|
// key: 'LostAccountsNotice',
|
||||||
|
// onConfirm: () => props.dispatch(actions.markAccountsFound()),
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
return {
|
||||||
|
noActiveNotices,
|
||||||
|
lastUnreadNotice,
|
||||||
|
lostAccounts,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Notice.propTypes = {
|
||||||
|
notice: PropTypes.object,
|
||||||
|
onConfirm: PropTypes.func,
|
||||||
|
history: PropTypes.object,
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
markNoticeRead: lastUnreadNotice => dispatch(actions.markNoticeRead(lastUnreadNotice)),
|
||||||
|
markAccountsFound: () => dispatch(actions.markAccountsFound()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||||
|
const { noActiveNotices, lastUnreadNotice, lostAccounts } = stateProps
|
||||||
|
const { markNoticeRead, markAccountsFound } = dispatchProps
|
||||||
|
|
||||||
|
let notice
|
||||||
|
let onConfirm
|
||||||
|
|
||||||
|
if (!noActiveNotices) {
|
||||||
|
notice = lastUnreadNotice
|
||||||
|
onConfirm = () => markNoticeRead(lastUnreadNotice)
|
||||||
|
} else if (lostAccounts && lostAccounts.length > 0) {
|
||||||
|
notice = generateLostAccountsNotice(lostAccounts)
|
||||||
|
onConfirm = () => markAccountsFound()
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...stateProps,
|
||||||
|
...dispatchProps,
|
||||||
|
...ownProps,
|
||||||
|
notice,
|
||||||
|
onConfirm,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = connect(mapStateToProps, mapDispatchToProps, mergeProps)(Notice)
|
59
ui/app/components/pages/settings/index.js
Normal file
59
ui/app/components/pages/settings/index.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
const { Component } = require('react')
|
||||||
|
const { Switch, Route, matchPath } = require('react-router-dom')
|
||||||
|
const PropTypes = require('prop-types')
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const TabBar = require('../../tab-bar')
|
||||||
|
const Settings = require('./settings')
|
||||||
|
const Info = require('./info')
|
||||||
|
const { SETTINGS_ROUTE, INFO_ROUTE } = require('../../../routes')
|
||||||
|
|
||||||
|
class Config extends Component {
|
||||||
|
renderTabs () {
|
||||||
|
const { history, location } = this.props
|
||||||
|
|
||||||
|
return h('div.settings__tabs', [
|
||||||
|
h(TabBar, {
|
||||||
|
tabs: [
|
||||||
|
{ content: 'Settings', key: SETTINGS_ROUTE },
|
||||||
|
{ content: 'Info', key: INFO_ROUTE },
|
||||||
|
],
|
||||||
|
isActive: key => matchPath(location.pathname, { path: key, exact: true }),
|
||||||
|
onSelect: key => history.push(key),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { history } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
h('.main-container.settings', {}, [
|
||||||
|
h('.settings__header', [
|
||||||
|
h('div.settings__close-button', {
|
||||||
|
onClick: () => history.push('/'),
|
||||||
|
}),
|
||||||
|
this.renderTabs(),
|
||||||
|
]),
|
||||||
|
h(Switch, [
|
||||||
|
h(Route, {
|
||||||
|
exact: true,
|
||||||
|
path: INFO_ROUTE,
|
||||||
|
component: Info,
|
||||||
|
}),
|
||||||
|
h(Route, {
|
||||||
|
exact: true,
|
||||||
|
path: SETTINGS_ROUTE,
|
||||||
|
component: Settings,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Config.propTypes = {
|
||||||
|
location: PropTypes.object,
|
||||||
|
history: PropTypes.object,
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Config
|
108
ui/app/components/pages/settings/info.js
Normal file
108
ui/app/components/pages/settings/info.js
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
const { Component } = require('react')
|
||||||
|
const PropTypes = require('prop-types')
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
|
||||||
|
class Info extends Component {
|
||||||
|
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!'),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
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(),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Info.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,
|
||||||
|
location: PropTypes.object,
|
||||||
|
history: PropTypes.object,
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Info
|
@ -1,14 +1,16 @@
|
|||||||
const { Component } = require('react')
|
const { Component } = require('react')
|
||||||
|
const { withRouter } = require('react-router-dom')
|
||||||
|
const { compose } = require('recompose')
|
||||||
const PropTypes = require('prop-types')
|
const PropTypes = require('prop-types')
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const { connect } = require('react-redux')
|
const { connect } = require('react-redux')
|
||||||
const actions = require('./actions')
|
const actions = require('../../../actions')
|
||||||
const infuraCurrencies = require('./infura-conversion.json')
|
const infuraCurrencies = require('../../../infura-conversion.json')
|
||||||
const validUrl = require('valid-url')
|
const validUrl = require('valid-url')
|
||||||
const { exportAsFile } = require('./util')
|
const { exportAsFile } = require('../../../util')
|
||||||
const TabBar = require('./components/tab-bar')
|
const SimpleDropdown = require('../../dropdowns/simple-dropdown')
|
||||||
const SimpleDropdown = require('./components/dropdowns/simple-dropdown')
|
|
||||||
const ToggleButton = require('react-toggle-button')
|
const ToggleButton = require('react-toggle-button')
|
||||||
|
const { REVEAL_SEED_ROUTE } = require('../../../routes')
|
||||||
|
|
||||||
const getInfuraCurrencyOptions = () => {
|
const getInfuraCurrencyOptions = () => {
|
||||||
const sortedCurrencies = infuraCurrencies.objects.sort((a, b) => {
|
const sortedCurrencies = infuraCurrencies.objects.sort((a, b) => {
|
||||||
@ -28,30 +30,11 @@ class Settings extends Component {
|
|||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
const { tab } = props
|
|
||||||
const activeTab = tab === 'info' ? 'info' : 'settings'
|
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
activeTab,
|
|
||||||
newRpc: '',
|
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 }),
|
|
||||||
}),
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
renderBlockieOptIn () {
|
renderBlockieOptIn () {
|
||||||
const { metamask: { useBlockie }, setUseBlockie } = this.props
|
const { metamask: { useBlockie }, setUseBlockie } = this.props
|
||||||
|
|
||||||
@ -210,7 +193,7 @@ class Settings extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderSeedWords () {
|
renderSeedWords () {
|
||||||
const { revealSeedConfirmation } = this.props
|
const { history } = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
h('div.settings__content-row', [
|
h('div.settings__content-row', [
|
||||||
@ -218,10 +201,7 @@ class Settings extends Component {
|
|||||||
h('div.settings__content-item', [
|
h('div.settings__content-item', [
|
||||||
h('div.settings__content-item-col', [
|
h('div.settings__content-item-col', [
|
||||||
h('button.settings__clear-button.settings__clear-button--red', {
|
h('button.settings__clear-button.settings__clear-button--red', {
|
||||||
onClick (event) {
|
onClick: () => history.push(REVEAL_SEED_ROUTE),
|
||||||
event.preventDefault()
|
|
||||||
revealSeedConfirmation()
|
|
||||||
},
|
|
||||||
}, 'Reveal Seed Words'),
|
}, 'Reveal Seed Words'),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
@ -249,7 +229,7 @@ class Settings extends Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSettingsContent () {
|
render () {
|
||||||
const { warning } = this.props
|
const { warning } = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -265,118 +245,9 @@ class Settings extends Component {
|
|||||||
])
|
])
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = {
|
Settings.propTypes = {
|
||||||
tab: PropTypes.string,
|
|
||||||
metamask: PropTypes.object,
|
metamask: PropTypes.object,
|
||||||
setUseBlockie: PropTypes.func,
|
setUseBlockie: PropTypes.func,
|
||||||
setCurrentCurrency: PropTypes.func,
|
setCurrentCurrency: PropTypes.func,
|
||||||
@ -385,7 +256,7 @@ Settings.propTypes = {
|
|||||||
revealSeedConfirmation: PropTypes.func,
|
revealSeedConfirmation: PropTypes.func,
|
||||||
setFeatureFlagToBeta: PropTypes.func,
|
setFeatureFlagToBeta: PropTypes.func,
|
||||||
warning: PropTypes.string,
|
warning: PropTypes.string,
|
||||||
goHome: PropTypes.func,
|
history: PropTypes.object,
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
@ -397,7 +268,6 @@ const mapStateToProps = state => {
|
|||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
const mapDispatchToProps = dispatch => {
|
||||||
return {
|
return {
|
||||||
goHome: () => dispatch(actions.goHome()),
|
|
||||||
setCurrentCurrency: currency => dispatch(actions.setCurrentCurrency(currency)),
|
setCurrentCurrency: currency => dispatch(actions.setCurrentCurrency(currency)),
|
||||||
setRpcTarget: newRpc => dispatch(actions.setRpcTarget(newRpc)),
|
setRpcTarget: newRpc => dispatch(actions.setRpcTarget(newRpc)),
|
||||||
displayWarning: warning => dispatch(actions.displayWarning(warning)),
|
displayWarning: warning => dispatch(actions.displayWarning(warning)),
|
||||||
@ -407,4 +277,7 @@ const mapDispatchToProps = dispatch => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(Settings)
|
module.exports = compose(
|
||||||
|
withRouter,
|
||||||
|
connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
)(Settings)
|
172
ui/app/components/pages/unauthenticated/unlock.js
Normal file
172
ui/app/components/pages/unauthenticated/unlock.js
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
const { Component } = require('react')
|
||||||
|
const PropTypes = require('prop-types')
|
||||||
|
const { connect } = require('react-redux')
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const { Redirect, withRouter } = require('react-router-dom')
|
||||||
|
const { compose } = require('recompose')
|
||||||
|
const { tryUnlockMetamask, forgotPassword } = require('../../../actions')
|
||||||
|
const getCaretCoordinates = require('textarea-caret')
|
||||||
|
const EventEmitter = require('events').EventEmitter
|
||||||
|
const Mascot = require('../../mascot')
|
||||||
|
const { DEFAULT_ROUTE, RESTORE_VAULT_ROUTE } = require('../../../routes')
|
||||||
|
|
||||||
|
class UnlockScreen extends Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
error: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
this.animationEventEmitter = new EventEmitter()
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
const passwordBox = document.getElementById('password-box')
|
||||||
|
|
||||||
|
if (passwordBox) {
|
||||||
|
passwordBox.focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tryUnlockMetamask (password) {
|
||||||
|
const { tryUnlockMetamask, history } = this.props
|
||||||
|
tryUnlockMetamask(password)
|
||||||
|
.then(() => history.push(DEFAULT_ROUTE))
|
||||||
|
.catch(({ message }) => this.setState({ error: message }))
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit (event) {
|
||||||
|
const input = document.getElementById('password-box')
|
||||||
|
const password = input.value
|
||||||
|
this.tryUnlockMetamask(password)
|
||||||
|
}
|
||||||
|
|
||||||
|
onKeyPress (event) {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
this.submitPassword(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
submitPassword (event) {
|
||||||
|
var element = event.target
|
||||||
|
var password = element.value
|
||||||
|
// reset input
|
||||||
|
element.value = ''
|
||||||
|
this.tryUnlockMetamask(password)
|
||||||
|
}
|
||||||
|
|
||||||
|
inputChanged (event) {
|
||||||
|
// tell mascot to look at page action
|
||||||
|
var element = event.target
|
||||||
|
var boundingRect = element.getBoundingClientRect()
|
||||||
|
var coordinates = getCaretCoordinates(element, element.selectionEnd)
|
||||||
|
this.animationEventEmitter.emit('point', {
|
||||||
|
x: boundingRect.left + coordinates.left - element.scrollLeft,
|
||||||
|
y: boundingRect.top + coordinates.top - element.scrollTop,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { error } = this.state
|
||||||
|
const { isUnlocked, history } = this.props
|
||||||
|
|
||||||
|
if (isUnlocked) {
|
||||||
|
return (
|
||||||
|
h(Redirect, {
|
||||||
|
to: {
|
||||||
|
pathname: DEFAULT_ROUTE,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
h('.unlock-page.main-container', [
|
||||||
|
h('.flex-column', {
|
||||||
|
style: {
|
||||||
|
width: 'inherit',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('.unlock-screen.flex-column.flex-center.flex-grow', [
|
||||||
|
|
||||||
|
h(Mascot, {
|
||||||
|
animationEventEmitter: this.animationEventEmitter,
|
||||||
|
}),
|
||||||
|
|
||||||
|
h('h1', {
|
||||||
|
style: {
|
||||||
|
fontSize: '1.4em',
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
color: '#7F8082',
|
||||||
|
},
|
||||||
|
}, 'MetaMask'),
|
||||||
|
|
||||||
|
h('input.large-input', {
|
||||||
|
type: 'password',
|
||||||
|
id: 'password-box',
|
||||||
|
placeholder: 'enter password',
|
||||||
|
style: {
|
||||||
|
background: 'white',
|
||||||
|
},
|
||||||
|
onKeyPress: this.onKeyPress.bind(this),
|
||||||
|
onInput: this.inputChanged.bind(this),
|
||||||
|
}),
|
||||||
|
|
||||||
|
h('.error', {
|
||||||
|
style: {
|
||||||
|
display: error ? 'block' : 'none',
|
||||||
|
padding: '0 20px',
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
}, error),
|
||||||
|
|
||||||
|
h('button.primary.cursor-pointer', {
|
||||||
|
onClick: this.onSubmit.bind(this),
|
||||||
|
style: {
|
||||||
|
margin: 10,
|
||||||
|
},
|
||||||
|
}, 'Unlock'),
|
||||||
|
|
||||||
|
h('.flex-row.flex-center.flex-grow', [
|
||||||
|
h('p.pointer', {
|
||||||
|
onClick: () => history.push(RESTORE_VAULT_ROUTE),
|
||||||
|
style: {
|
||||||
|
fontSize: '0.8em',
|
||||||
|
color: 'rgb(247, 134, 28)',
|
||||||
|
textDecoration: 'underline',
|
||||||
|
},
|
||||||
|
}, 'Restore from seed phrase'),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UnlockScreen.propTypes = {
|
||||||
|
forgotPassword: PropTypes.func,
|
||||||
|
tryUnlockMetamask: PropTypes.func,
|
||||||
|
history: PropTypes.object,
|
||||||
|
isUnlocked: PropTypes.bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
const { metamask: { isUnlocked } } = state
|
||||||
|
return {
|
||||||
|
isUnlocked,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
forgotPassword: () => dispatch(forgotPassword()),
|
||||||
|
tryUnlockMetamask: password => dispatch(tryUnlockMetamask(password)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = compose(
|
||||||
|
withRouter,
|
||||||
|
connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
)(UnlockScreen)
|
@ -1,5 +1,7 @@
|
|||||||
const Component = require('react').Component
|
const Component = require('react').Component
|
||||||
const { connect } = require('react-redux')
|
const { connect } = require('react-redux')
|
||||||
|
const { withRouter } = require('react-router-dom')
|
||||||
|
const { compose } = require('recompose')
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
const actions = require('../../actions')
|
const actions = require('../../actions')
|
||||||
@ -11,8 +13,12 @@ const hexToBn = require('../../../../app/scripts/lib/hex-to-bn')
|
|||||||
const { conversionUtil, addCurrencies } = require('../../conversion-util')
|
const { conversionUtil, addCurrencies } = require('../../conversion-util')
|
||||||
|
|
||||||
const { MIN_GAS_PRICE_HEX } = require('../send/send-constants')
|
const { MIN_GAS_PRICE_HEX } = require('../send/send-constants')
|
||||||
|
const { SEND_ROUTE, DEFAULT_ROUTE } = require('../../routes')
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmSendEther)
|
module.exports = compose(
|
||||||
|
withRouter,
|
||||||
|
connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
)(ConfirmSendEther)
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
const {
|
const {
|
||||||
@ -43,6 +49,7 @@ function mapDispatchToProps (dispatch) {
|
|||||||
to,
|
to,
|
||||||
value: amount,
|
value: amount,
|
||||||
} = txParams
|
} = txParams
|
||||||
|
|
||||||
dispatch(actions.updateSend({
|
dispatch(actions.updateSend({
|
||||||
gasLimit,
|
gasLimit,
|
||||||
gasPrice,
|
gasPrice,
|
||||||
@ -52,7 +59,6 @@ function mapDispatchToProps (dispatch) {
|
|||||||
errors: { to: null, amount: null },
|
errors: { to: null, amount: null },
|
||||||
editingTransactionId: id,
|
editingTransactionId: id,
|
||||||
}))
|
}))
|
||||||
dispatch(actions.showSendPage())
|
|
||||||
},
|
},
|
||||||
cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })),
|
cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })),
|
||||||
}
|
}
|
||||||
@ -177,8 +183,14 @@ ConfirmSendEther.prototype.getData = function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConfirmSendEther.prototype.editTransaction = function (txMeta) {
|
||||||
|
const { editTransaction, history } = this.props
|
||||||
|
editTransaction(txMeta)
|
||||||
|
history.push(SEND_ROUTE)
|
||||||
|
}
|
||||||
|
|
||||||
ConfirmSendEther.prototype.render = function () {
|
ConfirmSendEther.prototype.render = function () {
|
||||||
const { editTransaction, currentCurrency, clearSend } = this.props
|
const { currentCurrency, clearSend } = this.props
|
||||||
const txMeta = this.gatherTxMeta()
|
const txMeta = this.gatherTxMeta()
|
||||||
const txParams = txMeta.txParams || {}
|
const txParams = txMeta.txParams || {}
|
||||||
|
|
||||||
@ -220,7 +232,7 @@ ConfirmSendEther.prototype.render = function () {
|
|||||||
h('div.confirm-screen-wrapper.flex-column.flex-grow', [
|
h('div.confirm-screen-wrapper.flex-column.flex-grow', [
|
||||||
h('h3.flex-center.confirm-screen-header', [
|
h('h3.flex-center.confirm-screen-header', [
|
||||||
h('button.confirm-screen-back-button', {
|
h('button.confirm-screen-back-button', {
|
||||||
onClick: () => editTransaction(txMeta),
|
onClick: () => this.editTransaction(txMeta),
|
||||||
}, 'EDIT'),
|
}, 'EDIT'),
|
||||||
h('div.confirm-screen-title', 'Confirm Transaction'),
|
h('div.confirm-screen-title', 'Confirm Transaction'),
|
||||||
h('div.confirm-screen-header-tip'),
|
h('div.confirm-screen-header-tip'),
|
||||||
@ -422,6 +434,7 @@ ConfirmSendEther.prototype.onSubmit = function (event) {
|
|||||||
ConfirmSendEther.prototype.cancel = function (event, txMeta) {
|
ConfirmSendEther.prototype.cancel = function (event, txMeta) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
this.props.cancelTransaction(txMeta)
|
this.props.cancelTransaction(txMeta)
|
||||||
|
.then(() => this.props.history.push(DEFAULT_ROUTE))
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfirmSendEther.prototype.checkValidity = function () {
|
ConfirmSendEther.prototype.checkValidity = function () {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
const Component = require('react').Component
|
const Component = require('react').Component
|
||||||
const { connect } = require('react-redux')
|
const { connect } = require('react-redux')
|
||||||
|
const { withRouter } = require('react-router-dom')
|
||||||
|
const { compose } = require('recompose')
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
const ethAbi = require('ethereumjs-abi')
|
const ethAbi = require('ethereumjs-abi')
|
||||||
@ -27,8 +29,12 @@ const {
|
|||||||
getSelectedAddress,
|
getSelectedAddress,
|
||||||
getSelectedTokenContract,
|
getSelectedTokenContract,
|
||||||
} = require('../../selectors')
|
} = require('../../selectors')
|
||||||
|
const { SEND_ROUTE, DEFAULT_ROUTE } = require('../../routes')
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmSendToken)
|
module.exports = compose(
|
||||||
|
withRouter,
|
||||||
|
connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
)(ConfirmSendToken)
|
||||||
|
|
||||||
function mapStateToProps (state, ownProps) {
|
function mapStateToProps (state, ownProps) {
|
||||||
const { token: { symbol }, txData } = ownProps
|
const { token: { symbol }, txData } = ownProps
|
||||||
@ -99,6 +105,12 @@ function ConfirmSendToken () {
|
|||||||
this.onSubmit = this.onSubmit.bind(this)
|
this.onSubmit = this.onSubmit.bind(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConfirmSendToken.prototype.editTransaction = function (txMeta) {
|
||||||
|
const { editTransaction, history } = this.props
|
||||||
|
editTransaction(txMeta)
|
||||||
|
history.push(SEND_ROUTE)
|
||||||
|
}
|
||||||
|
|
||||||
ConfirmSendToken.prototype.componentWillMount = function () {
|
ConfirmSendToken.prototype.componentWillMount = function () {
|
||||||
const { tokenContract, selectedAddress } = this.props
|
const { tokenContract, selectedAddress } = this.props
|
||||||
tokenContract && tokenContract
|
tokenContract && tokenContract
|
||||||
@ -293,7 +305,6 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ConfirmSendToken.prototype.render = function () {
|
ConfirmSendToken.prototype.render = function () {
|
||||||
const { editTransaction } = this.props
|
|
||||||
const txMeta = this.gatherTxMeta()
|
const txMeta = this.gatherTxMeta()
|
||||||
const {
|
const {
|
||||||
from: {
|
from: {
|
||||||
@ -316,7 +327,7 @@ ConfirmSendToken.prototype.render = function () {
|
|||||||
h('div.confirm-screen-wrapper.flex-column.flex-grow', [
|
h('div.confirm-screen-wrapper.flex-column.flex-grow', [
|
||||||
h('h3.flex-center.confirm-screen-header', [
|
h('h3.flex-center.confirm-screen-header', [
|
||||||
h('button.confirm-screen-back-button', {
|
h('button.confirm-screen-back-button', {
|
||||||
onClick: () => editTransaction(txMeta),
|
onClick: () => this.editTransaction(txMeta),
|
||||||
}, 'EDIT'),
|
}, 'EDIT'),
|
||||||
h('div.confirm-screen-title', 'Confirm Transaction'),
|
h('div.confirm-screen-title', 'Confirm Transaction'),
|
||||||
h('div.confirm-screen-header-tip'),
|
h('div.confirm-screen-header-tip'),
|
||||||
@ -416,6 +427,7 @@ ConfirmSendToken.prototype.onSubmit = function (event) {
|
|||||||
ConfirmSendToken.prototype.cancel = function (event, txMeta) {
|
ConfirmSendToken.prototype.cancel = function (event, txMeta) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
this.props.cancelTransaction(txMeta)
|
this.props.cancelTransaction(txMeta)
|
||||||
|
.then(() => this.props.history.push(DEFAULT_ROUTE))
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfirmSendToken.prototype.checkValidity = function () {
|
ConfirmSendToken.prototype.checkValidity = function () {
|
||||||
|
@ -2,6 +2,8 @@ const connect = require('react-redux').connect
|
|||||||
const actions = require('../../actions')
|
const actions = require('../../actions')
|
||||||
const abi = require('ethereumjs-abi')
|
const abi = require('ethereumjs-abi')
|
||||||
const SendEther = require('../../send-v2')
|
const SendEther = require('../../send-v2')
|
||||||
|
const { withRouter } = require('react-router-dom')
|
||||||
|
const { compose } = require('recompose')
|
||||||
|
|
||||||
const {
|
const {
|
||||||
accountsWithSendEtherInfoSelector,
|
accountsWithSendEtherInfoSelector,
|
||||||
@ -16,7 +18,10 @@ const {
|
|||||||
getSelectedTokenContract,
|
getSelectedTokenContract,
|
||||||
} = require('../../selectors')
|
} = require('../../selectors')
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(SendEther)
|
module.exports = compose(
|
||||||
|
withRouter,
|
||||||
|
connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
)(SendEther)
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
const fromAccounts = accountsWithSendEtherInfoSelector(state)
|
const fromAccounts = accountsWithSendEtherInfoSelector(state)
|
||||||
|
@ -4,31 +4,17 @@ const PropTypes = require('react').PropTypes
|
|||||||
const classnames = require('classnames')
|
const classnames = require('classnames')
|
||||||
|
|
||||||
class TabBar extends Component {
|
class TabBar extends Component {
|
||||||
constructor (props) {
|
|
||||||
super(props)
|
|
||||||
const { defaultTab, tabs } = props
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
subview: defaultTab || tabs[0].key,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { tabs = [], tabSelected } = this.props
|
const { tabs = [], onSelect, isActive } = this.props
|
||||||
const { subview } = this.state
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
h('.tab-bar', {}, [
|
h('.tab-bar', {}, [
|
||||||
tabs.map((tab) => {
|
tabs.map(({ key, content }) => {
|
||||||
const { key, content } = tab
|
|
||||||
return h('div', {
|
return h('div', {
|
||||||
className: classnames('tab-bar__tab pointer', {
|
className: classnames('tab-bar__tab pointer', {
|
||||||
'tab-bar__tab--active': subview === key,
|
'tab-bar__tab--active': isActive(key, content),
|
||||||
}),
|
}),
|
||||||
onClick: () => {
|
onClick: () => onSelect(key),
|
||||||
this.setState({ subview: key })
|
|
||||||
tabSelected(key)
|
|
||||||
},
|
|
||||||
key,
|
key,
|
||||||
}, content)
|
}, content)
|
||||||
}),
|
}),
|
||||||
@ -39,9 +25,9 @@ class TabBar extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TabBar.propTypes = {
|
TabBar.propTypes = {
|
||||||
defaultTab: PropTypes.string,
|
isActive: PropTypes.func.isRequired,
|
||||||
tabs: PropTypes.array,
|
tabs: PropTypes.array,
|
||||||
tabSelected: PropTypes.func,
|
onSelect: PropTypes.func,
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = TabBar
|
module.exports = TabBar
|
||||||
|
@ -10,8 +10,14 @@ const { formatDate } = require('../util')
|
|||||||
const { showConfTxPage } = require('../actions')
|
const { showConfTxPage } = require('../actions')
|
||||||
const classnames = require('classnames')
|
const classnames = require('classnames')
|
||||||
const { tokenInfoGetter } = require('../token-util')
|
const { tokenInfoGetter } = require('../token-util')
|
||||||
|
const { withRouter } = require('react-router-dom')
|
||||||
|
const { compose } = require('recompose')
|
||||||
|
const { CONFIRM_TRANSACTION_ROUTE } = require('../routes')
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(TxList)
|
module.exports = compose(
|
||||||
|
withRouter,
|
||||||
|
connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
)(TxList)
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
return {
|
return {
|
||||||
@ -88,7 +94,7 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa
|
|||||||
transactionHash,
|
transactionHash,
|
||||||
transactionNetworkId,
|
transactionNetworkId,
|
||||||
} = props
|
} = props
|
||||||
const { showConfTxPage } = this.props
|
const { showConfTxPage, history } = this.props
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
key: transActionId || transactionHash,
|
key: transActionId || transactionHash,
|
||||||
@ -106,7 +112,7 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa
|
|||||||
const isUnapproved = transactionStatus === 'unapproved'
|
const isUnapproved = transactionStatus === 'unapproved'
|
||||||
|
|
||||||
if (isUnapproved) {
|
if (isUnapproved) {
|
||||||
opts.onClick = () => showConfTxPage({id: transActionId})
|
opts.onClick = () => history.push(CONFIRM_TRANSACTION_ROUTE)
|
||||||
opts.transactionStatus = 'Not Started'
|
opts.transactionStatus = 'Not Started'
|
||||||
} else if (transactionHash) {
|
} else if (transactionHash) {
|
||||||
opts.onClick = () => this.view(transactionHash, transactionNetworkId)
|
opts.onClick = () => this.view(transactionHash, transactionNetworkId)
|
||||||
|
@ -3,14 +3,20 @@ const connect = require('react-redux').connect
|
|||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
|
const { withRouter } = require('react-router-dom')
|
||||||
|
const { compose } = require('recompose')
|
||||||
const actions = require('../actions')
|
const actions = require('../actions')
|
||||||
const selectors = require('../selectors')
|
const selectors = require('../selectors')
|
||||||
|
const { SEND_ROUTE } = require('../routes')
|
||||||
|
|
||||||
const BalanceComponent = require('./balance-component')
|
const BalanceComponent = require('./balance-component')
|
||||||
const TxList = require('./tx-list')
|
const TxList = require('./tx-list')
|
||||||
const Identicon = require('./identicon')
|
const Identicon = require('./identicon')
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(TxView)
|
module.exports = compose(
|
||||||
|
withRouter,
|
||||||
|
connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
)(TxView)
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
const sidebarOpen = state.appState.sidebarOpen
|
const sidebarOpen = state.appState.sidebarOpen
|
||||||
@ -63,7 +69,7 @@ TxView.prototype.renderHeroBalance = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TxView.prototype.renderButtons = function () {
|
TxView.prototype.renderButtons = function () {
|
||||||
const {selectedToken, showModal, showSendPage, showSendTokenPage } = this.props
|
const {selectedToken, showModal, history } = this.props
|
||||||
|
|
||||||
return !selectedToken
|
return !selectedToken
|
||||||
? (
|
? (
|
||||||
@ -82,7 +88,7 @@ TxView.prototype.renderButtons = function () {
|
|||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
marginLeft: '0.8em',
|
marginLeft: '0.8em',
|
||||||
},
|
},
|
||||||
onClick: showSendPage,
|
onClick: () => history.push(SEND_ROUTE),
|
||||||
}, 'SEND'),
|
}, 'SEND'),
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
@ -93,7 +99,7 @@ TxView.prototype.renderButtons = function () {
|
|||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
marginLeft: '0.8em',
|
marginLeft: '0.8em',
|
||||||
},
|
},
|
||||||
onClick: showSendTokenPage,
|
onClick: () => history.push(SEND_ROUTE),
|
||||||
}, 'SEND'),
|
}, 'SEND'),
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
const Component = require('react').Component
|
const Component = require('react').Component
|
||||||
const connect = require('react-redux').connect
|
const connect = require('react-redux').connect
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
|
const { withRouter } = require('react-router-dom')
|
||||||
|
const { compose } = require('recompose')
|
||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
const Identicon = require('./identicon')
|
const Identicon = require('./identicon')
|
||||||
// const AccountDropdowns = require('./dropdowns/index.js').AccountDropdowns
|
// const AccountDropdowns = require('./dropdowns/index.js').AccountDropdowns
|
||||||
@ -9,8 +11,12 @@ const actions = require('../actions')
|
|||||||
const BalanceComponent = require('./balance-component')
|
const BalanceComponent = require('./balance-component')
|
||||||
const TokenList = require('./token-list')
|
const TokenList = require('./token-list')
|
||||||
const selectors = require('../selectors')
|
const selectors = require('../selectors')
|
||||||
|
const { ADD_TOKEN_ROUTE } = require('../routes')
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(WalletView)
|
module.exports = compose(
|
||||||
|
withRouter,
|
||||||
|
connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
)(WalletView)
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
|
|
||||||
@ -89,6 +95,7 @@ WalletView.prototype.render = function () {
|
|||||||
showAccountDetailModal,
|
showAccountDetailModal,
|
||||||
hideSidebar,
|
hideSidebar,
|
||||||
showAddTokenPage,
|
showAddTokenPage,
|
||||||
|
history,
|
||||||
} = this.props
|
} = this.props
|
||||||
// temporary logs + fake extra wallets
|
// temporary logs + fake extra wallets
|
||||||
// console.log('walletview, selectedAccount:', selectedAccount)
|
// console.log('walletview, selectedAccount:', selectedAccount)
|
||||||
@ -152,10 +159,7 @@ WalletView.prototype.render = function () {
|
|||||||
h(TokenList),
|
h(TokenList),
|
||||||
|
|
||||||
h('button.wallet-view__add-token-button', {
|
h('button.wallet-view__add-token-button', {
|
||||||
onClick: () => {
|
onClick: () => history.push(ADD_TOKEN_ROUTE),
|
||||||
showAddTokenPage()
|
|
||||||
hideSidebar()
|
|
||||||
},
|
|
||||||
}, 'Add Token'),
|
}, 'Add Token'),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ const inherits = require('util').inherits
|
|||||||
const Component = require('react').Component
|
const Component = require('react').Component
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const connect = require('react-redux').connect
|
const connect = require('react-redux').connect
|
||||||
|
const { withRouter } = require('react-router-dom')
|
||||||
|
const { compose } = require('recompose')
|
||||||
const actions = require('./actions')
|
const actions = require('./actions')
|
||||||
const txHelper = require('../lib/tx-helper')
|
const txHelper = require('../lib/tx-helper')
|
||||||
|
|
||||||
@ -11,17 +13,12 @@ const SignatureRequest = require('./components/signature-request')
|
|||||||
// const PendingPersonalMsg = require('./components/pending-personal-msg')
|
// const PendingPersonalMsg = require('./components/pending-personal-msg')
|
||||||
// const PendingTypedMsg = require('./components/pending-typed-msg')
|
// const PendingTypedMsg = require('./components/pending-typed-msg')
|
||||||
const Loading = require('./components/loading')
|
const Loading = require('./components/loading')
|
||||||
|
const { DEFAULT_ROUTE } = require('./routes')
|
||||||
|
|
||||||
// const contentDivider = h('div', {
|
module.exports = compose(
|
||||||
// style: {
|
withRouter,
|
||||||
// marginLeft: '16px',
|
connect(mapStateToProps)
|
||||||
// marginRight: '16px',
|
)(ConfirmTxScreen)
|
||||||
// height:'1px',
|
|
||||||
// background:'#E7E7E7',
|
|
||||||
// },
|
|
||||||
// })
|
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps)(ConfirmTxScreen)
|
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
return {
|
return {
|
||||||
@ -48,6 +45,20 @@ function ConfirmTxScreen () {
|
|||||||
Component.call(this)
|
Component.call(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConfirmTxScreen.prototype.componentWillMount = function () {
|
||||||
|
const { unapprovedTxs = {} } = this.props
|
||||||
|
if (Object.keys(unapprovedTxs).length === 0) {
|
||||||
|
this.props.history.push(DEFAULT_ROUTE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfirmTxScreen.prototype.componentWillReceiveProps = function (nextProps) {
|
||||||
|
const { unapprovedTxs = {} } = nextProps
|
||||||
|
if (Object.keys(unapprovedTxs).length === 0) {
|
||||||
|
this.props.history.push(DEFAULT_ROUTE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ConfirmTxScreen.prototype.render = function () {
|
ConfirmTxScreen.prototype.render = function () {
|
||||||
const props = this.props
|
const props = this.props
|
||||||
const {
|
const {
|
||||||
@ -146,6 +157,7 @@ ConfirmTxScreen.prototype.buyEth = function (address, event) {
|
|||||||
ConfirmTxScreen.prototype.sendTransaction = function (txData, event) {
|
ConfirmTxScreen.prototype.sendTransaction = function (txData, event) {
|
||||||
this.stopPropagation(event)
|
this.stopPropagation(event)
|
||||||
this.props.dispatch(actions.updateAndApproveTx(txData))
|
this.props.dispatch(actions.updateAndApproveTx(txData))
|
||||||
|
.then(() => this.props.history.push(DEFAULT_ROUTE))
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfirmTxScreen.prototype.cancelTransaction = function (txData, event) {
|
ConfirmTxScreen.prototype.cancelTransaction = function (txData, event) {
|
||||||
|
@ -6,9 +6,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@import './itcss/settings/index.scss';
|
@import './itcss/settings/index.scss';
|
||||||
|
|
||||||
@import './itcss/tools/index.scss';
|
@import './itcss/tools/index.scss';
|
||||||
|
|
||||||
@import './itcss/generic/index.scss';
|
@import './itcss/generic/index.scss';
|
||||||
|
|
||||||
@import './itcss/base/index.scss';
|
@import './itcss/base/index.scss';
|
||||||
|
|
||||||
@import './itcss/objects/index.scss';
|
@import './itcss/objects/index.scss';
|
||||||
|
|
||||||
@import './itcss/components/index.scss';
|
@import './itcss/components/index.scss';
|
||||||
|
|
||||||
@import './itcss/trumps/index.scss';
|
@import './itcss/trumps/index.scss';
|
||||||
|
@ -51,3 +51,5 @@
|
|||||||
@import './account-dropdown-mini.scss';
|
@import './account-dropdown-mini.scss';
|
||||||
|
|
||||||
@import './editable-label.scss';
|
@import './editable-label.scss';
|
||||||
|
|
||||||
|
@import './pages/index.scss';
|
||||||
|
1
ui/app/css/itcss/components/pages/index.scss
Normal file
1
ui/app/css/itcss/components/pages/index.scss
Normal file
@ -0,0 +1 @@
|
|||||||
|
@import './unlock.scss';
|
9
ui/app/css/itcss/components/pages/unlock.scss
Normal file
9
ui/app/css/itcss/components/pages/unlock.scss
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.unlock-page {
|
||||||
|
box-shadow: none;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: rgb(247, 247, 247);
|
||||||
|
width: 100%;
|
||||||
|
}
|
@ -17,6 +17,12 @@ textarea.twelve-word-phrase {
|
|||||||
resize: none;
|
resize: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.initialize-screen {
|
||||||
|
width: 100%;
|
||||||
|
z-index: $main-container-z-index;
|
||||||
|
background: #f7f7f7;
|
||||||
|
}
|
||||||
|
|
||||||
.initialize-screen hr {
|
.initialize-screen hr {
|
||||||
width: 60px;
|
width: 60px;
|
||||||
margin: 12px;
|
margin: 12px;
|
||||||
|
@ -1,184 +1,191 @@
|
|||||||
const inherits = require('util').inherits
|
const { EventEmitter } = require('events')
|
||||||
const EventEmitter = require('events').EventEmitter
|
const { Component } = require('react')
|
||||||
const Component = require('react').Component
|
const { connect } = require('react-redux')
|
||||||
const connect = require('react-redux').connect
|
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
|
const PropTypes = require('prop-types')
|
||||||
const Mascot = require('../components/mascot')
|
const Mascot = require('../components/mascot')
|
||||||
const actions = require('../actions')
|
const actions = require('../actions')
|
||||||
const Tooltip = require('../components/tooltip')
|
const Tooltip = require('../components/tooltip')
|
||||||
const getCaretCoordinates = require('textarea-caret')
|
const getCaretCoordinates = require('textarea-caret')
|
||||||
|
const { RESTORE_VAULT_ROUTE, DEFAULT_ROUTE } = require('../routes')
|
||||||
|
|
||||||
let isSubmitting = false
|
class InitializeMenuScreen extends Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps)(InitializeMenuScreen)
|
this.animationEventEmitter = new EventEmitter()
|
||||||
|
this.state = {
|
||||||
inherits(InitializeMenuScreen, Component)
|
warning: null,
|
||||||
function InitializeMenuScreen () {
|
}
|
||||||
Component.call(this)
|
|
||||||
this.animationEventEmitter = new EventEmitter()
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
|
||||||
return {
|
|
||||||
// state from plugin
|
|
||||||
currentView: state.appState.currentView,
|
|
||||||
warning: state.appState.warning,
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
InitializeMenuScreen.prototype.render = function () {
|
|
||||||
var state = this.props
|
|
||||||
|
|
||||||
switch (state.currentView.name) {
|
|
||||||
|
|
||||||
default:
|
|
||||||
return this.renderMenu(state)
|
|
||||||
|
|
||||||
|
componentWillMount () {
|
||||||
|
const { isInitialized, isUnlocked, history } = this.props
|
||||||
|
if (isInitialized || isUnlocked) {
|
||||||
|
history.push(DEFAULT_ROUTE)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// InitializeMenuScreen.prototype.componentDidMount = function(){
|
componentDidMount () {
|
||||||
// document.getElementById('password-box').focus()
|
document.getElementById('password-box').focus()
|
||||||
// }
|
}
|
||||||
|
|
||||||
InitializeMenuScreen.prototype.renderMenu = function (state) {
|
render () {
|
||||||
return (
|
const { history } = this.props
|
||||||
|
const { warning } = this.state
|
||||||
|
|
||||||
h('.initialize-screen.flex-column.flex-center.flex-grow', [
|
return (
|
||||||
|
h('.initialize-screen.flex-column.flex-center.flex-grow', [
|
||||||
|
|
||||||
h(Mascot, {
|
h(Mascot, {
|
||||||
animationEventEmitter: this.animationEventEmitter,
|
animationEventEmitter: this.animationEventEmitter,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
h('h1', {
|
h('h1', {
|
||||||
style: {
|
|
||||||
fontSize: '1.3em',
|
|
||||||
textTransform: 'uppercase',
|
|
||||||
color: '#7F8082',
|
|
||||||
marginBottom: 10,
|
|
||||||
},
|
|
||||||
}, 'MetaMask'),
|
|
||||||
|
|
||||||
|
|
||||||
h('div', [
|
|
||||||
h('h3', {
|
|
||||||
style: {
|
style: {
|
||||||
fontSize: '0.8em',
|
fontSize: '1.3em',
|
||||||
|
textTransform: 'uppercase',
|
||||||
color: '#7F8082',
|
color: '#7F8082',
|
||||||
display: 'inline',
|
marginBottom: 10,
|
||||||
},
|
},
|
||||||
}, 'Encrypt your new DEN'),
|
}, 'MetaMask'),
|
||||||
|
|
||||||
h(Tooltip, {
|
|
||||||
title: 'Your DEN is your password-encrypted storage within MetaMask.',
|
h('div', [
|
||||||
}, [
|
h('h3', {
|
||||||
h('i.fa.fa-question-circle.pointer', {
|
|
||||||
style: {
|
style: {
|
||||||
fontSize: '18px',
|
fontSize: '0.8em',
|
||||||
position: 'relative',
|
color: '#7F8082',
|
||||||
color: 'rgb(247, 134, 28)',
|
display: 'inline',
|
||||||
top: '2px',
|
|
||||||
marginLeft: '4px',
|
|
||||||
},
|
},
|
||||||
}),
|
}, 'Encrypt your new DEN'),
|
||||||
|
|
||||||
|
h(Tooltip, {
|
||||||
|
title: 'Your DEN is your password-encrypted storage within MetaMask.',
|
||||||
|
}, [
|
||||||
|
h('i.fa.fa-question-circle.pointer', {
|
||||||
|
style: {
|
||||||
|
fontSize: '18px',
|
||||||
|
position: 'relative',
|
||||||
|
color: 'rgb(247, 134, 28)',
|
||||||
|
top: '2px',
|
||||||
|
marginLeft: '4px',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]),
|
||||||
]),
|
]),
|
||||||
]),
|
|
||||||
|
|
||||||
h('span.in-progress-notification', state.warning),
|
h('span.error.in-progress-notification', warning),
|
||||||
|
|
||||||
// password
|
// password
|
||||||
h('input.large-input.letter-spacey', {
|
h('input.large-input.letter-spacey', {
|
||||||
type: 'password',
|
type: 'password',
|
||||||
id: 'password-box',
|
id: 'password-box',
|
||||||
placeholder: 'New Password (min 8 chars)',
|
placeholder: 'New Password (min 8 chars)',
|
||||||
onInput: this.inputChanged.bind(this),
|
onInput: this.inputChanged.bind(this),
|
||||||
style: {
|
|
||||||
width: 260,
|
|
||||||
marginTop: 12,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
// confirm password
|
|
||||||
h('input.large-input.letter-spacey', {
|
|
||||||
type: 'password',
|
|
||||||
id: 'password-box-confirm',
|
|
||||||
placeholder: 'Confirm Password',
|
|
||||||
onKeyPress: this.createVaultOnEnter.bind(this),
|
|
||||||
onInput: this.inputChanged.bind(this),
|
|
||||||
style: {
|
|
||||||
width: 260,
|
|
||||||
marginTop: 16,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
|
|
||||||
h('button.primary', {
|
|
||||||
onClick: this.createNewVaultAndKeychain.bind(this),
|
|
||||||
style: {
|
|
||||||
margin: 12,
|
|
||||||
},
|
|
||||||
}, 'Create'),
|
|
||||||
|
|
||||||
h('.flex-row.flex-center.flex-grow', [
|
|
||||||
h('p.pointer', {
|
|
||||||
onClick: this.showRestoreVault.bind(this),
|
|
||||||
style: {
|
style: {
|
||||||
fontSize: '0.8em',
|
width: 260,
|
||||||
color: 'rgb(247, 134, 28)',
|
marginTop: 12,
|
||||||
textDecoration: 'underline',
|
|
||||||
},
|
},
|
||||||
}, 'Import Existing DEN'),
|
}),
|
||||||
]),
|
|
||||||
|
|
||||||
])
|
// confirm password
|
||||||
)
|
h('input.large-input.letter-spacey', {
|
||||||
}
|
type: 'password',
|
||||||
|
id: 'password-box-confirm',
|
||||||
|
placeholder: 'Confirm Password',
|
||||||
|
onKeyPress: this.createVaultOnEnter.bind(this),
|
||||||
|
onInput: this.inputChanged.bind(this),
|
||||||
|
style: {
|
||||||
|
width: 260,
|
||||||
|
marginTop: 16,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
InitializeMenuScreen.prototype.createVaultOnEnter = function (event) {
|
|
||||||
if (event.key === 'Enter') {
|
h('button.primary', {
|
||||||
event.preventDefault()
|
onClick: this.createNewVaultAndKeychain.bind(this),
|
||||||
this.createNewVaultAndKeychain()
|
style: {
|
||||||
|
margin: 12,
|
||||||
|
},
|
||||||
|
}, 'Create'),
|
||||||
|
|
||||||
|
h('.flex-row.flex-center.flex-grow', [
|
||||||
|
h('p.pointer', {
|
||||||
|
onClick: () => history.push(RESTORE_VAULT_ROUTE),
|
||||||
|
style: {
|
||||||
|
fontSize: '0.8em',
|
||||||
|
color: 'rgb(247, 134, 28)',
|
||||||
|
textDecoration: 'underline',
|
||||||
|
},
|
||||||
|
}, 'Import Existing DEN'),
|
||||||
|
]),
|
||||||
|
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
createVaultOnEnter (event) {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
event.preventDefault()
|
||||||
|
this.createNewVaultAndKeychain()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createNewVaultAndKeychain () {
|
||||||
|
const { history } = this.props
|
||||||
|
var passwordBox = document.getElementById('password-box')
|
||||||
|
var password = passwordBox.value
|
||||||
|
var passwordConfirmBox = document.getElementById('password-box-confirm')
|
||||||
|
var passwordConfirm = passwordConfirmBox.value
|
||||||
|
|
||||||
|
this.setState({ warning: null })
|
||||||
|
|
||||||
|
if (password.length < 8) {
|
||||||
|
this.setState({ warning: 'password not long enough' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (password !== passwordConfirm) {
|
||||||
|
this.setState({ warning: 'passwords don\'t match' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.props.createNewVaultAndKeychain(password)
|
||||||
|
.then(() => history.push(DEFAULT_ROUTE))
|
||||||
|
}
|
||||||
|
|
||||||
|
inputChanged (event) {
|
||||||
|
// tell mascot to look at page action
|
||||||
|
var element = event.target
|
||||||
|
var boundingRect = element.getBoundingClientRect()
|
||||||
|
var coordinates = getCaretCoordinates(element, element.selectionEnd)
|
||||||
|
this.animationEventEmitter.emit('point', {
|
||||||
|
x: boundingRect.left + coordinates.left - element.scrollLeft,
|
||||||
|
y: boundingRect.top + coordinates.top - element.scrollTop,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InitializeMenuScreen.prototype.componentDidMount = function () {
|
InitializeMenuScreen.propTypes = {
|
||||||
document.getElementById('password-box').focus()
|
history: PropTypes.object,
|
||||||
|
isInitialized: PropTypes.bool,
|
||||||
|
isUnlocked: PropTypes.bool,
|
||||||
|
createNewVaultAndKeychain: PropTypes.func,
|
||||||
}
|
}
|
||||||
|
|
||||||
InitializeMenuScreen.prototype.showRestoreVault = function () {
|
const mapStateToProps = state => {
|
||||||
this.props.dispatch(actions.showRestoreVault())
|
const { metamask: { isInitialized, isUnlocked } } = state
|
||||||
}
|
|
||||||
|
|
||||||
InitializeMenuScreen.prototype.createNewVaultAndKeychain = function () {
|
return {
|
||||||
var passwordBox = document.getElementById('password-box')
|
isInitialized,
|
||||||
var password = passwordBox.value
|
isUnlocked,
|
||||||
var passwordConfirmBox = document.getElementById('password-box-confirm')
|
|
||||||
var passwordConfirm = passwordConfirmBox.value
|
|
||||||
|
|
||||||
if (password.length < 8) {
|
|
||||||
this.warning = 'password not long enough'
|
|
||||||
this.props.dispatch(actions.displayWarning(this.warning))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (password !== passwordConfirm) {
|
|
||||||
this.warning = 'passwords don\'t match'
|
|
||||||
this.props.dispatch(actions.displayWarning(this.warning))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isSubmitting) {
|
|
||||||
isSubmitting = true
|
|
||||||
this.props.dispatch(actions.createNewVaultAndKeychain(password))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InitializeMenuScreen.prototype.inputChanged = function (event) {
|
const mapDispatchToProps = dispatch => {
|
||||||
// tell mascot to look at page action
|
return {
|
||||||
var element = event.target
|
createNewVaultAndKeychain: password => dispatch(actions.createNewVaultAndKeychain(password)),
|
||||||
var boundingRect = element.getBoundingClientRect()
|
}
|
||||||
var coordinates = getCaretCoordinates(element, element.selectionEnd)
|
|
||||||
this.animationEventEmitter.emit('point', {
|
|
||||||
x: boundingRect.left + coordinates.left - element.scrollLeft,
|
|
||||||
y: boundingRect.top + coordinates.top - element.scrollTop,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = connect(mapStateToProps, mapDispatchToProps)(InitializeMenuScreen)
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
const inherits = require('util').inherits
|
|
||||||
const Component = require('react').Component
|
|
||||||
const connect = require('react-redux').connect
|
|
||||||
const h = require('react-hyperscript')
|
|
||||||
const actions = require('../../actions')
|
|
||||||
const exportAsFile = require('../../util').exportAsFile
|
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps)(CreateVaultCompleteScreen)
|
|
||||||
|
|
||||||
inherits(CreateVaultCompleteScreen, Component)
|
|
||||||
function CreateVaultCompleteScreen () {
|
|
||||||
Component.call(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
|
||||||
return {
|
|
||||||
seed: state.appState.currentView.seedWords,
|
|
||||||
cachedSeed: state.metamask.seedWords,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateVaultCompleteScreen.prototype.render = function () {
|
|
||||||
var state = this.props
|
|
||||||
var seed = state.seed || state.cachedSeed || ''
|
|
||||||
|
|
||||||
return (
|
|
||||||
|
|
||||||
h('.initialize-screen.flex-column.flex-center.flex-grow', [
|
|
||||||
|
|
||||||
// // subtitle and nav
|
|
||||||
// h('.section-title.flex-row.flex-center', [
|
|
||||||
// h('h2.page-subtitle', 'Vault Created'),
|
|
||||||
// ]),
|
|
||||||
|
|
||||||
h('h3.flex-center.text-transform-uppercase', {
|
|
||||||
style: {
|
|
||||||
background: '#EBEBEB',
|
|
||||||
color: '#AEAEAE',
|
|
||||||
marginTop: 36,
|
|
||||||
marginBottom: 8,
|
|
||||||
width: '100%',
|
|
||||||
fontSize: '20px',
|
|
||||||
padding: 6,
|
|
||||||
},
|
|
||||||
}, [
|
|
||||||
'Vault Created',
|
|
||||||
]),
|
|
||||||
|
|
||||||
h('div', {
|
|
||||||
style: {
|
|
||||||
fontSize: '1em',
|
|
||||||
marginTop: '10px',
|
|
||||||
textAlign: 'center',
|
|
||||||
},
|
|
||||||
}, [
|
|
||||||
h('span.error', 'These 12 words are the only way to restore your MetaMask accounts.\nSave them somewhere safe and secret.'),
|
|
||||||
]),
|
|
||||||
|
|
||||||
h('textarea.twelve-word-phrase', {
|
|
||||||
readOnly: true,
|
|
||||||
value: seed,
|
|
||||||
}),
|
|
||||||
|
|
||||||
h('button.primary', {
|
|
||||||
onClick: () => this.confirmSeedWords()
|
|
||||||
.then(account => this.showAccountDetail(account)),
|
|
||||||
style: {
|
|
||||||
margin: '24px',
|
|
||||||
fontSize: '0.9em',
|
|
||||||
marginBottom: '10px',
|
|
||||||
},
|
|
||||||
}, 'I\'ve copied it somewhere safe'),
|
|
||||||
|
|
||||||
h('button.primary', {
|
|
||||||
onClick: () => exportAsFile(`MetaMask Seed Words`, seed),
|
|
||||||
style: {
|
|
||||||
margin: '10px',
|
|
||||||
fontSize: '0.9em',
|
|
||||||
},
|
|
||||||
}, 'Save Seed Words As File'),
|
|
||||||
])
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateVaultCompleteScreen.prototype.confirmSeedWords = function () {
|
|
||||||
return this.props.dispatch(actions.confirmSeedWords())
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateVaultCompleteScreen.prototype.showAccountDetail = function (account) {
|
|
||||||
return this.props.dispatch(actions.showAccountDetail(account))
|
|
||||||
}
|
|
@ -1,121 +0,0 @@
|
|||||||
const inherits = require('util').inherits
|
|
||||||
|
|
||||||
const Component = require('react').Component
|
|
||||||
const connect = require('react-redux').connect
|
|
||||||
const h = require('react-hyperscript')
|
|
||||||
const actions = require('../../../actions')
|
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps)(RevealSeedConfirmation)
|
|
||||||
|
|
||||||
inherits(RevealSeedConfirmation, Component)
|
|
||||||
function RevealSeedConfirmation () {
|
|
||||||
Component.call(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
|
||||||
return {
|
|
||||||
warning: state.appState.warning,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RevealSeedConfirmation.prototype.render = function () {
|
|
||||||
const props = this.props
|
|
||||||
|
|
||||||
return (
|
|
||||||
|
|
||||||
h('.initialize-screen.flex-column.flex-center.flex-grow', {
|
|
||||||
style: { maxWidth: '420px' },
|
|
||||||
}, [
|
|
||||||
|
|
||||||
h('h3.flex-center.text-transform-uppercase', {
|
|
||||||
style: {
|
|
||||||
background: '#EBEBEB',
|
|
||||||
color: '#AEAEAE',
|
|
||||||
marginBottom: 24,
|
|
||||||
width: '100%',
|
|
||||||
fontSize: '20px',
|
|
||||||
padding: 6,
|
|
||||||
},
|
|
||||||
}, [
|
|
||||||
'Reveal Seed Words',
|
|
||||||
]),
|
|
||||||
|
|
||||||
h('.div', {
|
|
||||||
style: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
padding: '20px',
|
|
||||||
justifyContent: 'center',
|
|
||||||
},
|
|
||||||
}, [
|
|
||||||
|
|
||||||
h('h4', 'Do not recover your seed words in a public place! These words can be used to steal all your accounts.'),
|
|
||||||
|
|
||||||
// confirmation
|
|
||||||
h('input.large-input.letter-spacey', {
|
|
||||||
type: 'password',
|
|
||||||
id: 'password-box',
|
|
||||||
placeholder: 'Enter your password to confirm',
|
|
||||||
onKeyPress: this.checkConfirmation.bind(this),
|
|
||||||
style: {
|
|
||||||
width: 260,
|
|
||||||
marginTop: '12px',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
h('.flex-row.flex-start', {
|
|
||||||
style: {
|
|
||||||
marginTop: 30,
|
|
||||||
width: '50%',
|
|
||||||
},
|
|
||||||
}, [
|
|
||||||
// cancel
|
|
||||||
h('button.primary', {
|
|
||||||
onClick: this.goHome.bind(this),
|
|
||||||
}, 'CANCEL'),
|
|
||||||
|
|
||||||
// submit
|
|
||||||
h('button.primary', {
|
|
||||||
style: { marginLeft: '10px' },
|
|
||||||
onClick: this.revealSeedWords.bind(this),
|
|
||||||
}, 'OK'),
|
|
||||||
|
|
||||||
]),
|
|
||||||
|
|
||||||
(props.warning) && (
|
|
||||||
h('span.error', {
|
|
||||||
style: {
|
|
||||||
margin: '20px',
|
|
||||||
},
|
|
||||||
}, props.warning.split('-'))
|
|
||||||
),
|
|
||||||
|
|
||||||
props.inProgress && (
|
|
||||||
h('span.in-progress-notification', 'Generating Seed...')
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
])
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
RevealSeedConfirmation.prototype.componentDidMount = function () {
|
|
||||||
document.getElementById('password-box').focus()
|
|
||||||
}
|
|
||||||
|
|
||||||
RevealSeedConfirmation.prototype.goHome = function () {
|
|
||||||
this.props.dispatch(actions.showConfigPage(false))
|
|
||||||
}
|
|
||||||
|
|
||||||
// create vault
|
|
||||||
|
|
||||||
RevealSeedConfirmation.prototype.checkConfirmation = function (event) {
|
|
||||||
if (event.key === 'Enter') {
|
|
||||||
event.preventDefault()
|
|
||||||
this.revealSeedWords()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RevealSeedConfirmation.prototype.revealSeedWords = function () {
|
|
||||||
var password = document.getElementById('password-box').value
|
|
||||||
this.props.dispatch(actions.requestRevealSeed(password))
|
|
||||||
}
|
|
@ -1,152 +0,0 @@
|
|||||||
const inherits = require('util').inherits
|
|
||||||
const PersistentForm = require('../../../lib/persistent-form')
|
|
||||||
const connect = require('react-redux').connect
|
|
||||||
const h = require('react-hyperscript')
|
|
||||||
const actions = require('../../actions')
|
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps)(RestoreVaultScreen)
|
|
||||||
|
|
||||||
inherits(RestoreVaultScreen, PersistentForm)
|
|
||||||
function RestoreVaultScreen () {
|
|
||||||
PersistentForm.call(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
|
||||||
return {
|
|
||||||
warning: state.appState.warning,
|
|
||||||
forgottenPassword: state.appState.forgottenPassword,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RestoreVaultScreen.prototype.render = function () {
|
|
||||||
var state = this.props
|
|
||||||
this.persistentFormParentId = 'restore-vault-form'
|
|
||||||
|
|
||||||
return (
|
|
||||||
|
|
||||||
h('.initialize-screen.flex-column.flex-center.flex-grow', [
|
|
||||||
|
|
||||||
h('h3.flex-center.text-transform-uppercase', {
|
|
||||||
style: {
|
|
||||||
background: '#EBEBEB',
|
|
||||||
color: '#AEAEAE',
|
|
||||||
marginBottom: 24,
|
|
||||||
width: '100%',
|
|
||||||
fontSize: '20px',
|
|
||||||
padding: 6,
|
|
||||||
},
|
|
||||||
}, [
|
|
||||||
'Restore Vault',
|
|
||||||
]),
|
|
||||||
|
|
||||||
// wallet seed entry
|
|
||||||
h('h3', 'Wallet Seed'),
|
|
||||||
h('textarea.twelve-word-phrase.letter-spacey', {
|
|
||||||
dataset: {
|
|
||||||
persistentFormId: 'wallet-seed',
|
|
||||||
},
|
|
||||||
placeholder: 'Enter your secret twelve word phrase here to restore your vault.',
|
|
||||||
}),
|
|
||||||
|
|
||||||
// password
|
|
||||||
h('input.large-input.letter-spacey', {
|
|
||||||
type: 'password',
|
|
||||||
id: 'password-box',
|
|
||||||
placeholder: 'New Password (min 8 chars)',
|
|
||||||
dataset: {
|
|
||||||
persistentFormId: 'password',
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
width: 260,
|
|
||||||
marginTop: 12,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
// confirm password
|
|
||||||
h('input.large-input.letter-spacey', {
|
|
||||||
type: 'password',
|
|
||||||
id: 'password-box-confirm',
|
|
||||||
placeholder: 'Confirm Password',
|
|
||||||
onKeyPress: this.createOnEnter.bind(this),
|
|
||||||
dataset: {
|
|
||||||
persistentFormId: 'password-confirmation',
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
width: 260,
|
|
||||||
marginTop: 16,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
(state.warning) && (
|
|
||||||
h('span.error.in-progress-notification', state.warning)
|
|
||||||
),
|
|
||||||
|
|
||||||
// submit
|
|
||||||
|
|
||||||
h('.flex-row.flex-space-between', {
|
|
||||||
style: {
|
|
||||||
marginTop: 30,
|
|
||||||
width: '50%',
|
|
||||||
},
|
|
||||||
}, [
|
|
||||||
|
|
||||||
// cancel
|
|
||||||
h('button.primary', {
|
|
||||||
onClick: this.showInitializeMenu.bind(this),
|
|
||||||
}, 'CANCEL'),
|
|
||||||
|
|
||||||
// submit
|
|
||||||
h('button.primary', {
|
|
||||||
onClick: this.createNewVaultAndRestore.bind(this),
|
|
||||||
}, 'OK'),
|
|
||||||
|
|
||||||
]),
|
|
||||||
])
|
|
||||||
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
RestoreVaultScreen.prototype.showInitializeMenu = function () {
|
|
||||||
if (this.props.forgottenPassword) {
|
|
||||||
this.props.dispatch(actions.backToUnlockView())
|
|
||||||
} else {
|
|
||||||
this.props.dispatch(actions.showInitializeMenu())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RestoreVaultScreen.prototype.createOnEnter = function (event) {
|
|
||||||
if (event.key === 'Enter') {
|
|
||||||
this.createNewVaultAndRestore()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RestoreVaultScreen.prototype.createNewVaultAndRestore = function () {
|
|
||||||
// check password
|
|
||||||
var passwordBox = document.getElementById('password-box')
|
|
||||||
var password = passwordBox.value
|
|
||||||
var passwordConfirmBox = document.getElementById('password-box-confirm')
|
|
||||||
var passwordConfirm = passwordConfirmBox.value
|
|
||||||
if (password.length < 8) {
|
|
||||||
this.warning = 'Password not long enough'
|
|
||||||
|
|
||||||
this.props.dispatch(actions.displayWarning(this.warning))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (password !== passwordConfirm) {
|
|
||||||
this.warning = 'Passwords don\'t match'
|
|
||||||
this.props.dispatch(actions.displayWarning(this.warning))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// check seed
|
|
||||||
var seedBox = document.querySelector('textarea.twelve-word-phrase')
|
|
||||||
var seed = seedBox.value.trim()
|
|
||||||
if (seed.split(' ').length !== 12) {
|
|
||||||
this.warning = 'seed phrases are 12 words long'
|
|
||||||
this.props.dispatch(actions.displayWarning(this.warning))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// submit
|
|
||||||
this.warning = null
|
|
||||||
this.props.dispatch(actions.displayWarning(this.warning))
|
|
||||||
this.props.dispatch(actions.createNewVaultAndRestore(password, seed))
|
|
||||||
}
|
|
@ -2,9 +2,7 @@ const Component = require('react').Component
|
|||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
const AccountAndTransactionDetails = require('./account-and-transaction-details')
|
const AccountAndTransactionDetails = require('./account-and-transaction-details')
|
||||||
const HDRestoreVaultScreen = require('./keychains/hd/restore-vault')
|
const UnlockScreen = require('./components/pages/unauthenticated/unlock')
|
||||||
const Settings = require('./settings')
|
|
||||||
const UnlockScreen = require('./unlock')
|
|
||||||
|
|
||||||
module.exports = MainContainer
|
module.exports = MainContainer
|
||||||
|
|
||||||
@ -26,36 +24,6 @@ MainContainer.prototype.render = function () {
|
|||||||
style: {},
|
style: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.isUnlocked === false) {
|
|
||||||
switch (this.props.currentViewName) {
|
|
||||||
case 'restoreVault':
|
|
||||||
log.debug('rendering restore vault screen')
|
|
||||||
contents = {
|
|
||||||
component: HDRestoreVaultScreen,
|
|
||||||
key: 'HDRestoreVaultScreen',
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case 'config':
|
|
||||||
log.debug('rendering config screen from unlock screen.')
|
|
||||||
return h(Settings, {key: 'config'})
|
|
||||||
default:
|
|
||||||
log.debug('rendering locked screen')
|
|
||||||
contents = {
|
|
||||||
component: UnlockScreen,
|
|
||||||
style: {
|
|
||||||
boxShadow: 'none',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
background: '#F7F7F7',
|
|
||||||
// must force 100%, because lock screen is full-width
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
key: 'locked',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return h('div.main-container', {
|
return h('div.main-container', {
|
||||||
style: contents.style,
|
style: contents.style,
|
||||||
}, [
|
}, [
|
||||||
|
@ -1,22 +1,28 @@
|
|||||||
const inherits = require('util').inherits
|
const { Component } = require('react')
|
||||||
const Component = require('react').Component
|
const PropTypes = require('prop-types')
|
||||||
const Provider = require('react-redux').Provider
|
const { Provider } = require('react-redux')
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const SelectedApp = require('./select-app')
|
const SelectedApp = require('./select-app')
|
||||||
|
const { HashRouter } = require('react-router-dom')
|
||||||
|
|
||||||
|
class Root extends Component {
|
||||||
|
render () {
|
||||||
|
const { store } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
h(Provider, { store }, [
|
||||||
|
h(HashRouter, {
|
||||||
|
hashType: 'noslash',
|
||||||
|
}, [
|
||||||
|
h(SelectedApp),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Root.propTypes = {
|
||||||
|
store: PropTypes.object,
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = Root
|
module.exports = Root
|
||||||
|
|
||||||
inherits(Root, Component)
|
|
||||||
function Root () { Component.call(this) }
|
|
||||||
|
|
||||||
Root.prototype.render = function () {
|
|
||||||
return (
|
|
||||||
|
|
||||||
h(Provider, {
|
|
||||||
store: this.props.store,
|
|
||||||
}, [
|
|
||||||
h(SelectedApp),
|
|
||||||
])
|
|
||||||
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
27
ui/app/routes.js
Normal file
27
ui/app/routes.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
const DEFAULT_ROUTE = '/'
|
||||||
|
const UNLOCK_ROUTE = '/unlock'
|
||||||
|
const SETTINGS_ROUTE = '/settings'
|
||||||
|
const INFO_ROUTE = '/settings/info'
|
||||||
|
const REVEAL_SEED_ROUTE = '/reveal-seed-confirm'
|
||||||
|
const RESTORE_VAULT_ROUTE = '/restore-vault'
|
||||||
|
const ADD_TOKEN_ROUTE = '/add-token'
|
||||||
|
const IMPORT_ACCOUNT_ROUTE = '/import-account'
|
||||||
|
const SEND_ROUTE = '/send'
|
||||||
|
const CONFIRM_TRANSACTION_ROUTE = '/confirm-transaction'
|
||||||
|
const INITIALIZE_MENU_ROUTE = '/initialize-menu'
|
||||||
|
const NOTICE_ROUTE = '/notice'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
DEFAULT_ROUTE,
|
||||||
|
UNLOCK_ROUTE,
|
||||||
|
SETTINGS_ROUTE,
|
||||||
|
INFO_ROUTE,
|
||||||
|
REVEAL_SEED_ROUTE,
|
||||||
|
RESTORE_VAULT_ROUTE,
|
||||||
|
ADD_TOKEN_ROUTE,
|
||||||
|
IMPORT_ACCOUNT_ROUTE,
|
||||||
|
SEND_ROUTE,
|
||||||
|
CONFIRM_TRANSACTION_ROUTE,
|
||||||
|
INITIALIZE_MENU_ROUTE,
|
||||||
|
NOTICE_ROUTE,
|
||||||
|
}
|
@ -28,6 +28,7 @@ const {
|
|||||||
isTokenBalanceSufficient,
|
isTokenBalanceSufficient,
|
||||||
} = require('./components/send/send-utils')
|
} = require('./components/send/send-utils')
|
||||||
const { isValidAddress } = require('./util')
|
const { isValidAddress } = require('./util')
|
||||||
|
const { CONFIRM_TRANSACTION_ROUTE } = require('./routes')
|
||||||
|
|
||||||
module.exports = SendTransactionScreen
|
module.exports = SendTransactionScreen
|
||||||
|
|
||||||
@ -508,9 +509,9 @@ SendTransactionScreen.prototype.renderForm = function () {
|
|||||||
|
|
||||||
SendTransactionScreen.prototype.renderFooter = function () {
|
SendTransactionScreen.prototype.renderFooter = function () {
|
||||||
const {
|
const {
|
||||||
goHome,
|
|
||||||
clearSend,
|
clearSend,
|
||||||
errors: { amount: amountError, to: toError },
|
errors: { amount: amountError, to: toError },
|
||||||
|
history,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
const noErrors = !amountError && toError === null
|
const noErrors = !amountError && toError === null
|
||||||
@ -520,7 +521,7 @@ SendTransactionScreen.prototype.renderFooter = function () {
|
|||||||
h('button.send-v2__cancel-btn', {
|
h('button.send-v2__cancel-btn', {
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
clearSend()
|
clearSend()
|
||||||
goHome()
|
history.goBack()
|
||||||
},
|
},
|
||||||
}, 'Cancel'),
|
}, 'Cancel'),
|
||||||
h(`button.send-v2__next-btn${errorClass}`, {
|
h(`button.send-v2__next-btn${errorClass}`, {
|
||||||
@ -555,7 +556,7 @@ SendTransactionScreen.prototype.addToAddressBookIfNew = function (newAddress) {
|
|||||||
SendTransactionScreen.prototype.onSubmit = function (event) {
|
SendTransactionScreen.prototype.onSubmit = function (event) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
const {
|
const {
|
||||||
from: {address: from},
|
from: { address: from },
|
||||||
to,
|
to,
|
||||||
amount,
|
amount,
|
||||||
gasLimit: gas,
|
gasLimit: gas,
|
||||||
@ -578,6 +579,7 @@ SendTransactionScreen.prototype.onSubmit = function (event) {
|
|||||||
|
|
||||||
if (editingTransactionId) {
|
if (editingTransactionId) {
|
||||||
backToConfirmScreen(editingTransactionId)
|
backToConfirmScreen(editingTransactionId)
|
||||||
|
this.props.history.push(CONFIRM_TRANSACTION_ROUTE)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -596,4 +598,6 @@ SendTransactionScreen.prototype.onSubmit = function (event) {
|
|||||||
selectedToken
|
selectedToken
|
||||||
? signTokenTx(selectedToken.address, to, amount, txParams)
|
? signTokenTx(selectedToken.address, to, amount, txParams)
|
||||||
: signTx(txParams)
|
: signTx(txParams)
|
||||||
|
|
||||||
|
this.props.history.push(CONFIRM_TRANSACTION_ROUTE)
|
||||||
}
|
}
|
||||||
|
122
ui/app/unlock.js
122
ui/app/unlock.js
@ -1,122 +0,0 @@
|
|||||||
const inherits = require('util').inherits
|
|
||||||
const Component = require('react').Component
|
|
||||||
const h = require('react-hyperscript')
|
|
||||||
const connect = require('react-redux').connect
|
|
||||||
const actions = require('./actions')
|
|
||||||
const getCaretCoordinates = require('textarea-caret')
|
|
||||||
const EventEmitter = require('events').EventEmitter
|
|
||||||
|
|
||||||
const Mascot = require('./components/mascot')
|
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps)(UnlockScreen)
|
|
||||||
|
|
||||||
inherits(UnlockScreen, Component)
|
|
||||||
function UnlockScreen () {
|
|
||||||
Component.call(this)
|
|
||||||
this.animationEventEmitter = new EventEmitter()
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
|
||||||
return {
|
|
||||||
warning: state.appState.warning,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UnlockScreen.prototype.render = function () {
|
|
||||||
const state = this.props
|
|
||||||
const warning = state.warning
|
|
||||||
return (
|
|
||||||
h('.flex-column', {
|
|
||||||
style: {
|
|
||||||
width: 'inherit',
|
|
||||||
},
|
|
||||||
}, [
|
|
||||||
h('.unlock-screen.flex-column.flex-center.flex-grow', [
|
|
||||||
|
|
||||||
h(Mascot, {
|
|
||||||
animationEventEmitter: this.animationEventEmitter,
|
|
||||||
}),
|
|
||||||
|
|
||||||
h('h1', {
|
|
||||||
style: {
|
|
||||||
fontSize: '1.4em',
|
|
||||||
textTransform: 'uppercase',
|
|
||||||
color: '#7F8082',
|
|
||||||
},
|
|
||||||
}, 'MetaMask'),
|
|
||||||
|
|
||||||
h('input.large-input', {
|
|
||||||
type: 'password',
|
|
||||||
id: 'password-box',
|
|
||||||
placeholder: 'enter password',
|
|
||||||
style: {
|
|
||||||
background: 'white',
|
|
||||||
},
|
|
||||||
onKeyPress: this.onKeyPress.bind(this),
|
|
||||||
onInput: this.inputChanged.bind(this),
|
|
||||||
}),
|
|
||||||
|
|
||||||
h('.error', {
|
|
||||||
style: {
|
|
||||||
display: warning ? 'block' : 'none',
|
|
||||||
padding: '0 20px',
|
|
||||||
textAlign: 'center',
|
|
||||||
},
|
|
||||||
}, warning),
|
|
||||||
|
|
||||||
h('button.primary.cursor-pointer', {
|
|
||||||
onClick: this.onSubmit.bind(this),
|
|
||||||
style: {
|
|
||||||
margin: 10,
|
|
||||||
},
|
|
||||||
}, 'Unlock'),
|
|
||||||
]),
|
|
||||||
|
|
||||||
h('.flex-row.flex-center.flex-grow', [
|
|
||||||
h('p.pointer', {
|
|
||||||
onClick: () => this.props.dispatch(actions.forgotPassword()),
|
|
||||||
style: {
|
|
||||||
fontSize: '0.8em',
|
|
||||||
color: 'rgb(247, 134, 28)',
|
|
||||||
textDecoration: 'underline',
|
|
||||||
},
|
|
||||||
}, 'Restore from seed phrase'),
|
|
||||||
]),
|
|
||||||
])
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
UnlockScreen.prototype.componentDidMount = function () {
|
|
||||||
document.getElementById('password-box').focus()
|
|
||||||
}
|
|
||||||
|
|
||||||
UnlockScreen.prototype.onSubmit = function (event) {
|
|
||||||
const input = document.getElementById('password-box')
|
|
||||||
const password = input.value
|
|
||||||
this.props.dispatch(actions.tryUnlockMetamask(password))
|
|
||||||
}
|
|
||||||
|
|
||||||
UnlockScreen.prototype.onKeyPress = function (event) {
|
|
||||||
if (event.key === 'Enter') {
|
|
||||||
this.submitPassword(event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UnlockScreen.prototype.submitPassword = function (event) {
|
|
||||||
var element = event.target
|
|
||||||
var password = element.value
|
|
||||||
// reset input
|
|
||||||
element.value = ''
|
|
||||||
this.props.dispatch(actions.tryUnlockMetamask(password))
|
|
||||||
}
|
|
||||||
|
|
||||||
UnlockScreen.prototype.inputChanged = function (event) {
|
|
||||||
// tell mascot to look at page action
|
|
||||||
var element = event.target
|
|
||||||
var boundingRect = element.getBoundingClientRect()
|
|
||||||
var coordinates = getCaretCoordinates(element, element.selectionEnd)
|
|
||||||
this.animationEventEmitter.emit('point', {
|
|
||||||
x: boundingRect.left + coordinates.left - element.scrollLeft,
|
|
||||||
y: boundingRect.top + coordinates.top - element.scrollTop,
|
|
||||||
})
|
|
||||||
}
|
|
89
yarn.lock
89
yarn.lock
@ -20,8 +20,13 @@
|
|||||||
through2 "^2.0.3"
|
through2 "^2.0.3"
|
||||||
|
|
||||||
"@types/node@*":
|
"@types/node@*":
|
||||||
|
<<<<<<< HEAD
|
||||||
version "8.0.58"
|
version "8.0.58"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.58.tgz#5b3881c0be3a646874803fee3197ea7f1ed6df90"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.58.tgz#5b3881c0be3a646874803fee3197ea7f1ed6df90"
|
||||||
|
=======
|
||||||
|
version "8.0.53"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.53.tgz#396b35af826fa66aad472c8cb7b8d5e277f4e6d8"
|
||||||
|
>>>>>>> Add react-router to allow use of the browser back button
|
||||||
|
|
||||||
"@types/node@^6.0.46":
|
"@types/node@^6.0.46":
|
||||||
version "6.0.88"
|
version "6.0.88"
|
||||||
@ -3155,6 +3160,7 @@ envify@^4.0.0:
|
|||||||
enzyme-adapter-react-15@^1.0.5:
|
enzyme-adapter-react-15@^1.0.5:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/enzyme-adapter-react-15/-/enzyme-adapter-react-15-1.0.5.tgz#99f9a03ff2c2303e517342935798a6bdfbb75fac"
|
resolved "https://registry.yarnpkg.com/enzyme-adapter-react-15/-/enzyme-adapter-react-15-1.0.5.tgz#99f9a03ff2c2303e517342935798a6bdfbb75fac"
|
||||||
|
<<<<<<< HEAD
|
||||||
dependencies:
|
dependencies:
|
||||||
enzyme-adapter-utils "^1.1.0"
|
enzyme-adapter-utils "^1.1.0"
|
||||||
lodash "^4.17.4"
|
lodash "^4.17.4"
|
||||||
@ -3166,6 +3172,19 @@ enzyme-adapter-utils@^1.1.0:
|
|||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.2.0.tgz#7f4471ee0a70b91169ec8860d2bf0a6b551664b2"
|
resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.2.0.tgz#7f4471ee0a70b91169ec8860d2bf0a6b551664b2"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
=======
|
||||||
|
dependencies:
|
||||||
|
enzyme-adapter-utils "^1.1.0"
|
||||||
|
lodash "^4.17.4"
|
||||||
|
object.assign "^4.0.4"
|
||||||
|
object.values "^1.0.4"
|
||||||
|
prop-types "^15.5.10"
|
||||||
|
|
||||||
|
enzyme-adapter-utils@^1.1.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.2.0.tgz#7f4471ee0a70b91169ec8860d2bf0a6b551664b2"
|
||||||
|
dependencies:
|
||||||
|
>>>>>>> Add react-router to allow use of the browser back button
|
||||||
lodash "^4.17.4"
|
lodash "^4.17.4"
|
||||||
object.assign "^4.0.4"
|
object.assign "^4.0.4"
|
||||||
prop-types "^15.5.10"
|
prop-types "^15.5.10"
|
||||||
@ -3813,11 +3832,19 @@ ethjs-query@^0.2.4, ethjs-query@^0.2.6, ethjs-query@^0.2.9:
|
|||||||
ethjs-rpc "0.1.5"
|
ethjs-rpc "0.1.5"
|
||||||
|
|
||||||
ethjs-query@^0.3.1:
|
ethjs-query@^0.3.1:
|
||||||
|
<<<<<<< HEAD
|
||||||
version "0.3.2"
|
version "0.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/ethjs-query/-/ethjs-query-0.3.2.tgz#f488a48ce1994cd4c77eccb7b52902c6f29cfd85"
|
resolved "https://registry.yarnpkg.com/ethjs-query/-/ethjs-query-0.3.2.tgz#f488a48ce1994cd4c77eccb7b52902c6f29cfd85"
|
||||||
dependencies:
|
dependencies:
|
||||||
ethjs-format "0.2.4"
|
ethjs-format "0.2.4"
|
||||||
ethjs-rpc "0.1.8"
|
ethjs-rpc "0.1.8"
|
||||||
|
=======
|
||||||
|
version "0.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ethjs-query/-/ethjs-query-0.3.1.tgz#aed5b60bdb7e73ad831d1218c8b067310013b86f"
|
||||||
|
dependencies:
|
||||||
|
ethjs-format "0.2.4"
|
||||||
|
ethjs-rpc "0.1.5"
|
||||||
|
>>>>>>> Add react-router to allow use of the browser back button
|
||||||
|
|
||||||
ethjs-rpc@0.1.5:
|
ethjs-rpc@0.1.5:
|
||||||
version "0.1.5"
|
version "0.1.5"
|
||||||
@ -5044,6 +5071,16 @@ he@1.1.1:
|
|||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
|
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
|
||||||
|
|
||||||
|
history@^4.7.2:
|
||||||
|
version "4.7.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/history/-/history-4.7.2.tgz#22b5c7f31633c5b8021c7f4a8a954ac139ee8d5b"
|
||||||
|
dependencies:
|
||||||
|
invariant "^2.2.1"
|
||||||
|
loose-envify "^1.2.0"
|
||||||
|
resolve-pathname "^2.2.0"
|
||||||
|
value-equal "^0.4.0"
|
||||||
|
warning "^3.0.0"
|
||||||
|
|
||||||
hmac-drbg@^1.0.0:
|
hmac-drbg@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
|
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
|
||||||
@ -5060,7 +5097,7 @@ hoist-non-react-statics@^1.0.0:
|
|||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb"
|
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb"
|
||||||
|
|
||||||
hoist-non-react-statics@^2.2.1:
|
hoist-non-react-statics@^2.2.1, hoist-non-react-statics@^2.3.0:
|
||||||
version "2.3.1"
|
version "2.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz#343db84c6018c650778898240135a1420ee22ce0"
|
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz#343db84c6018c650778898240135a1420ee22ce0"
|
||||||
|
|
||||||
@ -5316,7 +5353,7 @@ interpret@^1.0.0:
|
|||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.4.tgz#820cdd588b868ffb191a809506d6c9c8f212b1b0"
|
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.4.tgz#820cdd588b868ffb191a809506d6c9c8f212b1b0"
|
||||||
|
|
||||||
invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.2:
|
invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2:
|
||||||
version "2.2.2"
|
version "2.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
|
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -6435,7 +6472,7 @@ longest@^1.0.1:
|
|||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
|
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
|
||||||
|
|
||||||
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1:
|
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1:
|
||||||
version "1.3.1"
|
version "1.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
|
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -7919,7 +7956,11 @@ prop-types@^15.5.10, prop-types@^15.5.6, prop-types@^15.5.8:
|
|||||||
fbjs "^0.8.9"
|
fbjs "^0.8.9"
|
||||||
loose-envify "^1.3.1"
|
loose-envify "^1.3.1"
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
prop-types@^15.5.7, prop-types@^15.6.0:
|
prop-types@^15.5.7, prop-types@^15.6.0:
|
||||||
|
=======
|
||||||
|
prop-types@^15.5.4, prop-types@^15.5.7, prop-types@^15.6.0:
|
||||||
|
>>>>>>> Add react-router to allow use of the browser back button
|
||||||
version "15.6.0"
|
version "15.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856"
|
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -8197,6 +8238,14 @@ react-motion@^0.5.2:
|
|||||||
prop-types "^15.5.8"
|
prop-types "^15.5.8"
|
||||||
raf "^3.1.0"
|
raf "^3.1.0"
|
||||||
|
|
||||||
|
react-motion@^0.5.2:
|
||||||
|
version "0.5.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-motion/-/react-motion-0.5.2.tgz#0dd3a69e411316567927917c6626551ba0607316"
|
||||||
|
dependencies:
|
||||||
|
performance-now "^0.2.0"
|
||||||
|
prop-types "^15.5.8"
|
||||||
|
raf "^3.1.0"
|
||||||
|
|
||||||
react-redux@^5.0.5:
|
react-redux@^5.0.5:
|
||||||
version "5.0.6"
|
version "5.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.6.tgz#23ed3a4f986359d68b5212eaaa681e60d6574946"
|
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.6.tgz#23ed3a4f986359d68b5212eaaa681e60d6574946"
|
||||||
@ -8208,6 +8257,32 @@ react-redux@^5.0.5:
|
|||||||
loose-envify "^1.1.0"
|
loose-envify "^1.1.0"
|
||||||
prop-types "^15.5.10"
|
prop-types "^15.5.10"
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
react-router-dom@^4.2.2:
|
||||||
|
version "4.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.2.2.tgz#c8a81df3adc58bba8a76782e946cbd4eae649b8d"
|
||||||
|
dependencies:
|
||||||
|
history "^4.7.2"
|
||||||
|
invariant "^2.2.2"
|
||||||
|
loose-envify "^1.3.1"
|
||||||
|
prop-types "^15.5.4"
|
||||||
|
react-router "^4.2.0"
|
||||||
|
warning "^3.0.0"
|
||||||
|
|
||||||
|
react-router@^4.2.0:
|
||||||
|
version "4.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.2.0.tgz#61f7b3e3770daeb24062dae3eedef1b054155986"
|
||||||
|
dependencies:
|
||||||
|
history "^4.7.2"
|
||||||
|
hoist-non-react-statics "^2.3.0"
|
||||||
|
invariant "^2.2.2"
|
||||||
|
loose-envify "^1.3.1"
|
||||||
|
path-to-regexp "^1.7.0"
|
||||||
|
prop-types "^15.5.4"
|
||||||
|
warning "^3.0.0"
|
||||||
|
|
||||||
|
>>>>>>> Add react-router to allow use of the browser back button
|
||||||
react-select@^1.0.0:
|
react-select@^1.0.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-select/-/react-select-1.1.0.tgz#626a2de839fdea2ade74dd1b143a9bde34be6c82"
|
resolved "https://registry.yarnpkg.com/react-select/-/react-select-1.1.0.tgz#626a2de839fdea2ade74dd1b143a9bde34be6c82"
|
||||||
@ -8668,6 +8743,10 @@ resolve-from@^3.0.0:
|
|||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
|
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
|
||||||
|
|
||||||
|
resolve-pathname@^2.2.0:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.2.0.tgz#7e9ae21ed815fd63ab189adeee64dc831eefa879"
|
||||||
|
|
||||||
resolve-url@~0.2.1:
|
resolve-url@~0.2.1:
|
||||||
version "0.2.1"
|
version "0.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
|
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
|
||||||
@ -10287,6 +10366,10 @@ validate-npm-package-license@^3.0.1:
|
|||||||
spdx-correct "~1.0.0"
|
spdx-correct "~1.0.0"
|
||||||
spdx-expression-parse "~1.0.0"
|
spdx-expression-parse "~1.0.0"
|
||||||
|
|
||||||
|
value-equal@^0.4.0:
|
||||||
|
version "0.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.4.0.tgz#c5bdd2f54ee093c04839d71ce2e4758a6890abc7"
|
||||||
|
|
||||||
varint@^4.0.0:
|
varint@^4.0.0:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/varint/-/varint-4.0.1.tgz#490829b942d248463b2b35097995c3bf737198e9"
|
resolved "https://registry.yarnpkg.com/varint/-/varint-4.0.1.tgz#490829b942d248463b2b35097995c3bf737198e9"
|
||||||
|
Loading…
Reference in New Issue
Block a user