Merge pull request #389 from poanetwork/vb-24-words-mnemoinc
Support 24 words mnemonic phrase
This commit is contained in:
commit
fed51b2f03
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
## Current Master
|
## Current Master
|
||||||
|
|
||||||
|
- [#389](https://github.com/poanetwork/nifty-wallet/pull/389) - (Feature) Support 24 words mnemonic phrase
|
||||||
- [#388](https://github.com/poanetwork/nifty-wallet/pull/388) - (Feature) "Send all" option for simple coin transfers
|
- [#388](https://github.com/poanetwork/nifty-wallet/pull/388) - (Feature) "Send all" option for simple coin transfers
|
||||||
- [#385](https://github.com/poanetwork/nifty-wallet/pull/385) - (Feature) Display value of current pending tx's nonce on send tx screen
|
- [#385](https://github.com/poanetwork/nifty-wallet/pull/385) - (Feature) Display value of current pending tx's nonce on send tx screen
|
||||||
- [#384](https://github.com/poanetwork/nifty-wallet/pull/384) - (Fix) placement of HW Connect button title
|
- [#384](https://github.com/poanetwork/nifty-wallet/pull/384) - (Fix) placement of HW Connect button title
|
||||||
|
|
|
@ -41,7 +41,8 @@ class ImportSeedPhraseScreen extends Component {
|
||||||
let seedPhraseError = null
|
let seedPhraseError = null
|
||||||
|
|
||||||
if (seedPhrase) {
|
if (seedPhrase) {
|
||||||
if (this.parseSeedPhrase(seedPhrase).split(' ').length !== 12) {
|
const wordsCount = this.parseSeedPhrase(seedPhrase).split(' ').length
|
||||||
|
if (wordsCount !== 12 && wordsCount !== 24) {
|
||||||
seedPhraseError = this.context.t('seedPhraseReq')
|
seedPhraseError = this.context.t('seedPhraseReq')
|
||||||
} else if (!validateMnemonic(seedPhrase)) {
|
} else if (!validateMnemonic(seedPhrase)) {
|
||||||
seedPhraseError = this.context.t('invalidSeedPhrase')
|
seedPhraseError = this.context.t('invalidSeedPhrase')
|
||||||
|
|
|
@ -1,15 +1,83 @@
|
||||||
const inherits = require('util').inherits
|
import { Component } from 'react'
|
||||||
const Component = require('react').Component
|
import { connect } from 'react-redux'
|
||||||
const connect = require('react-redux').connect
|
import PropTypes from 'prop-types'
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const actions = require('../../../../ui/app/actions')
|
const { confirmSeedWords, showAccountDetail } = require('../../../../ui/app/actions')
|
||||||
const exportAsFile = require('../../util').exportAsFile
|
const { exportAsFile } = require('../../util')
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps)(CreateVaultCompleteScreen)
|
class CreateVaultCompleteScreen extends Component {
|
||||||
|
|
||||||
inherits(CreateVaultCompleteScreen, Component)
|
static propTypes = {
|
||||||
function CreateVaultCompleteScreen () {
|
seed: PropTypes.string,
|
||||||
Component.call(this)
|
cachedSeed: PropTypes.string,
|
||||||
|
confirmSeedWords: PropTypes.func,
|
||||||
|
showAccountDetail: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const state = this.props
|
||||||
|
const seed = state.seed || state.cachedSeed || ''
|
||||||
|
const wordsCount = seed.split(' ').length
|
||||||
|
|
||||||
|
return (
|
||||||
|
|
||||||
|
h('.initialize-screen.flex-column.flex-center.flex-grow', [
|
||||||
|
|
||||||
|
h('h3.flex-center.section-title', {
|
||||||
|
style: {
|
||||||
|
background: '#ffffff',
|
||||||
|
color: '#333333',
|
||||||
|
marginBottom: 8,
|
||||||
|
width: '100%',
|
||||||
|
padding: '30px 6px 6px 6px',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
'Vault Created',
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('div', {
|
||||||
|
style: {
|
||||||
|
fontSize: '1em',
|
||||||
|
margin: '10px 30px',
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('div.error', `These ${wordsCount} words are the only way to restore your Nifty Wallet accounts.\nSave them somewhere safe and secret.`),
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('textarea.twelve-word-phrase', {
|
||||||
|
readOnly: true,
|
||||||
|
value: seed,
|
||||||
|
}),
|
||||||
|
|
||||||
|
h('button', {
|
||||||
|
onClick: () => this.confirmSeedWords()
|
||||||
|
.then(account => this.showAccountDetail(account)),
|
||||||
|
style: {
|
||||||
|
margin: '24px',
|
||||||
|
fontSize: '0.9em',
|
||||||
|
marginBottom: '10px',
|
||||||
|
},
|
||||||
|
}, 'I\'ve copied it somewhere safe'),
|
||||||
|
|
||||||
|
h('button', {
|
||||||
|
onClick: () => exportAsFile(`Nifty Wallet Seed Words`, seed),
|
||||||
|
style: {
|
||||||
|
margin: '10px',
|
||||||
|
fontSize: '0.9em',
|
||||||
|
},
|
||||||
|
}, 'Save Seed Words As File'),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
confirmSeedWords () {
|
||||||
|
return this.props.confirmSeedWords()
|
||||||
|
}
|
||||||
|
|
||||||
|
showAccountDetail (account) {
|
||||||
|
return this.props.showAccountDetail(account)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
|
@ -19,71 +87,11 @@ function mapStateToProps (state) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateVaultCompleteScreen.prototype.render = function () {
|
function mapDispatchToProps (dispatch) {
|
||||||
const state = this.props
|
return {
|
||||||
const seed = state.seed || state.cachedSeed || ''
|
confirmSeedWords: () => dispatch(confirmSeedWords()),
|
||||||
|
showAccountDetail: (account) => dispatch(showAccountDetail(account)),
|
||||||
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.section-title', {
|
|
||||||
style: {
|
|
||||||
background: '#ffffff',
|
|
||||||
color: '#333333',
|
|
||||||
marginBottom: 8,
|
|
||||||
width: '100%',
|
|
||||||
padding: '30px 6px 6px 6px',
|
|
||||||
},
|
|
||||||
}, [
|
|
||||||
'Vault Created',
|
|
||||||
]),
|
|
||||||
|
|
||||||
h('div', {
|
|
||||||
style: {
|
|
||||||
fontSize: '1em',
|
|
||||||
margin: '10px 30px',
|
|
||||||
textAlign: 'center',
|
|
||||||
},
|
|
||||||
}, [
|
|
||||||
h('div.error', 'These 12 words are the only way to restore your Nifty Wallet accounts.\nSave them somewhere safe and secret.'),
|
|
||||||
]),
|
|
||||||
|
|
||||||
h('textarea.twelve-word-phrase', {
|
|
||||||
readOnly: true,
|
|
||||||
value: seed,
|
|
||||||
}),
|
|
||||||
|
|
||||||
h('button', {
|
|
||||||
onClick: () => this.confirmSeedWords()
|
|
||||||
.then(account => this.showAccountDetail(account)),
|
|
||||||
style: {
|
|
||||||
margin: '24px',
|
|
||||||
fontSize: '0.9em',
|
|
||||||
marginBottom: '10px',
|
|
||||||
},
|
|
||||||
}, 'I\'ve copied it somewhere safe'),
|
|
||||||
|
|
||||||
h('button', {
|
|
||||||
onClick: () => exportAsFile(`Nifty Wallet Seed Words`, seed),
|
|
||||||
style: {
|
|
||||||
margin: '10px',
|
|
||||||
fontSize: '0.9em',
|
|
||||||
},
|
|
||||||
}, 'Save Seed Words As File'),
|
|
||||||
])
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateVaultCompleteScreen.prototype.confirmSeedWords = function () {
|
module.exports = connect(mapStateToProps, mapDispatchToProps)(CreateVaultCompleteScreen)
|
||||||
return this.props.dispatch(actions.confirmSeedWords())
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateVaultCompleteScreen.prototype.showAccountDetail = function (account) {
|
|
||||||
return this.props.dispatch(actions.showAccountDetail(account))
|
|
||||||
}
|
|
||||||
|
|
|
@ -179,8 +179,9 @@ RestoreVaultScreen.prototype.createNewVaultAndRestore = function () {
|
||||||
this.props.dispatch(actions.displayWarning(this.warning))
|
this.props.dispatch(actions.displayWarning(this.warning))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (seed.split(' ').length !== 12) {
|
const wordsCount = seed.split(' ').length
|
||||||
this.warning = 'seed phrases are 12 words long'
|
if (wordsCount !== 12 && wordsCount !== 24) {
|
||||||
|
this.warning = 'seed phrases are 12 or 24 words long'
|
||||||
this.props.dispatch(actions.displayWarning(this.warning))
|
this.props.dispatch(actions.displayWarning(this.warning))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -25149,7 +25149,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mkdirp": {
|
"mkdirp": {
|
||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"resolved": "",
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||||
|
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
|
@ -26507,7 +26508,8 @@
|
||||||
},
|
},
|
||||||
"decompress": {
|
"decompress": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "",
|
"resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz",
|
||||||
|
"integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"decompress-tar": "^4.0.0",
|
"decompress-tar": "^4.0.0",
|
||||||
"decompress-tarbz2": "^4.0.0",
|
"decompress-tarbz2": "^4.0.0",
|
||||||
|
@ -35601,7 +35603,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||||
|
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35622,7 +35625,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mkdirp": {
|
"mkdirp": {
|
||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"resolved": "",
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||||
|
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const { screens, menus, NETWORKS } = require('../elements')
|
const { screens, menus, NETWORKS } = require('../elements')
|
||||||
const testSeedPhrase = 'horn among position unable audit puzzle cannon apology gun autumn plug parrot'
|
const testSeedPhrase = 'horn among position unable audit puzzle cannon apology gun autumn plug parrot'
|
||||||
|
const test24SeedPhrase = 'gravity trophy shrimp suspect sheriff avocado label trust dove tragic pitch title network myself spell task protect smooth sword diary brain blossom under bulb'
|
||||||
|
|
||||||
const importGanacheSeedPhrase = async (f, account2, password) => {
|
const importGanacheSeedPhrase = async (f, account2, password) => {
|
||||||
it('logs out', async () => {
|
it('logs out', async () => {
|
||||||
|
@ -12,6 +13,38 @@ const importGanacheSeedPhrase = async (f, account2, password) => {
|
||||||
await logOut.click()
|
await logOut.click()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('restores from 24 seed phrase', async () => {
|
||||||
|
const restoreSeedLink = await f.waitUntilShowUp(screens.lock.linkRestore)
|
||||||
|
assert.equal(await restoreSeedLink.getText(), screens.lock.linkRestoreText)
|
||||||
|
await restoreSeedLink.click()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('adds 24 words seed phrase', async () => {
|
||||||
|
const seedTextArea = await f.waitUntilShowUp(screens.restoreVault.textArea)
|
||||||
|
await seedTextArea.sendKeys(test24SeedPhrase)
|
||||||
|
|
||||||
|
let field = await f.driver.findElement(screens.restoreVault.fieldPassword)
|
||||||
|
await field.sendKeys(password)
|
||||||
|
field = await f.driver.findElement(screens.restoreVault.fieldPasswordConfirm)
|
||||||
|
await field.sendKeys(password)
|
||||||
|
field = await f.waitUntilShowUp(screens.restoreVault.buttos.ok)
|
||||||
|
await f.click(field)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('balance renders', async () => {
|
||||||
|
const balance = await f.waitUntilShowUp(screens.main.balance)
|
||||||
|
assert.equal(await balance.getText(), '0', "balance isn't correct")
|
||||||
|
})
|
||||||
|
|
||||||
|
it('logs out', async () => {
|
||||||
|
await f.setProvider(NETWORKS.LOCALHOST)
|
||||||
|
const menu = await f.waitUntilShowUp(menus.sandwich.menu)
|
||||||
|
await menu.click()
|
||||||
|
const logOut = await f.waitUntilShowUp(menus.sandwich.logOut)
|
||||||
|
assert.equal(await logOut.getText(), menus.sandwich.textLogOut)
|
||||||
|
await logOut.click()
|
||||||
|
})
|
||||||
|
|
||||||
it('restores from seed phrase', async () => {
|
it('restores from seed phrase', async () => {
|
||||||
const restoreSeedLink = await f.waitUntilShowUp(screens.lock.linkRestore)
|
const restoreSeedLink = await f.waitUntilShowUp(screens.lock.linkRestore)
|
||||||
assert.equal(await restoreSeedLink.getText(), screens.lock.linkRestoreText)
|
assert.equal(await restoreSeedLink.getText(), screens.lock.linkRestoreText)
|
||||||
|
|
Loading…
Reference in New Issue