mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Merge branch 'i328-MultiVault' of github.com:MetaMask/metamask-plugin into i328-MultiVault
This commit is contained in:
commit
9b4f3825e7
@ -11,8 +11,10 @@ const createId = require('web3-provider-engine/util/random-id')
|
||||
|
||||
// Keyrings:
|
||||
const SimpleKeyring = require('./keyrings/simple')
|
||||
const HdKeyring = require('./keyrings/hd')
|
||||
const keyringTypes = [
|
||||
SimpleKeyring,
|
||||
HdKeyring,
|
||||
]
|
||||
|
||||
module.exports = class KeyringController extends EventEmitter {
|
||||
@ -67,7 +69,12 @@ module.exports = class KeyringController extends EventEmitter {
|
||||
})
|
||||
.then((encryptedString) => {
|
||||
this.configManager.setVault(encryptedString)
|
||||
cb(null, this.getState())
|
||||
|
||||
// TEMPORARY SINGLE-KEYRING CONFIG:
|
||||
this.addNewKeyring('HD Key Tree', null, cb)
|
||||
|
||||
// NORMAL BEHAVIOR:
|
||||
// cb(null, this.getState())
|
||||
})
|
||||
.catch((err) => {
|
||||
cb(err)
|
||||
@ -97,25 +104,35 @@ module.exports = class KeyringController extends EventEmitter {
|
||||
}
|
||||
|
||||
addNewKeyring(type, opts, cb) {
|
||||
const i = this.getAccounts().length
|
||||
const Keyring = this.getKeyringClassForType(type)
|
||||
const keyring = new Keyring(opts)
|
||||
const accounts = keyring.addAccounts(1)
|
||||
|
||||
accounts.forEach((account) => {
|
||||
this.loadBalanceAndNickname(account, i)
|
||||
})
|
||||
|
||||
this.setupAccounts(accounts)
|
||||
this.keyrings.push(keyring)
|
||||
this.persistAllKeyrings()
|
||||
.then(() => {
|
||||
cb(this.getState())
|
||||
cb(null, this.getState())
|
||||
})
|
||||
.catch((reason) => {
|
||||
cb(reason)
|
||||
})
|
||||
}
|
||||
|
||||
addNewAccount(keyRingNum = 0, cb) {
|
||||
const ring = this.keyrings[keyRingNum]
|
||||
const accounts = ring.addAccounts(1)
|
||||
this.setupAccounts(accounts)
|
||||
cb(null, this.getState())
|
||||
}
|
||||
|
||||
setupAccounts(accounts) {
|
||||
const i = this.getAccounts().length
|
||||
accounts.forEach((account) => {
|
||||
this.loadBalanceAndNickname(account, i)
|
||||
})
|
||||
}
|
||||
|
||||
// Takes an account address and an iterator representing
|
||||
// the current number of named accounts.
|
||||
loadBalanceAndNickname(account, i) {
|
||||
|
86
app/scripts/keyrings/hd.js
Normal file
86
app/scripts/keyrings/hd.js
Normal file
@ -0,0 +1,86 @@
|
||||
const EventEmitter = require('events').EventEmitter
|
||||
const hdkey = require('ethereumjs-wallet/hdkey')
|
||||
const bip39 = require('bip39')
|
||||
const ethUtil = require('ethereumjs-util')
|
||||
const type = 'HD Key Tree'
|
||||
const sigUtil = require('../lib/sig-util')
|
||||
|
||||
const hdPathString = `m/44'/60'/0'/0`
|
||||
|
||||
module.exports = class HdKeyring extends EventEmitter {
|
||||
|
||||
static type() {
|
||||
return type
|
||||
}
|
||||
|
||||
constructor(opts) {
|
||||
super()
|
||||
this.type = type
|
||||
this.opts = opts || {}
|
||||
this.wallets = []
|
||||
this.mnemonic = null
|
||||
}
|
||||
|
||||
deserialize({ mnemonic, n }) {
|
||||
this.initFromMnemonic(mnemonic || bip39.generateMnemonic())
|
||||
this.addAccounts(n)
|
||||
}
|
||||
|
||||
initFromMnemonic(mnemonic) {
|
||||
const seed = bip39.mnemonicToSeed(mnemonic)
|
||||
this.mnemonic = mnemonic
|
||||
this.hdWallet = hdkey.fromMasterSeed(seed)
|
||||
this.root = this.hdWallet.derivePath(hdPathString)
|
||||
}
|
||||
|
||||
serialize() {
|
||||
return {
|
||||
mnemonic: this.mnemonic,
|
||||
n: this.wallets.length,
|
||||
}
|
||||
}
|
||||
|
||||
addAccounts(n = 1) {
|
||||
if (!this.root) {
|
||||
this.initFromMnemonic(bip39.generateMnemonic())
|
||||
}
|
||||
|
||||
const oldLen = this.wallets.length
|
||||
const newWallets = []
|
||||
for (let i = oldLen; i < n + oldLen; i++) {
|
||||
const child = this.root.deriveChild(i)
|
||||
const wallet = child.getWallet()
|
||||
newWallets.push(wallet)
|
||||
this.wallets.push(wallet)
|
||||
}
|
||||
return newWallets.map(w => w.getAddress().toString('hex'))
|
||||
}
|
||||
|
||||
getAccounts() {
|
||||
return this.wallets.map(w => w.getAddress().toString('hex'))
|
||||
}
|
||||
|
||||
// tx is an instance of the ethereumjs-transaction class.
|
||||
signTransaction(address, tx) {
|
||||
const wallet = this.getWalletForAccount(address)
|
||||
var privKey = wallet.getPrivateKey()
|
||||
tx.sign(privKey)
|
||||
return tx
|
||||
}
|
||||
|
||||
// For eth_sign, we need to sign transactions:
|
||||
signMessage(withAccount, data) {
|
||||
const wallet = this.getWalletForAccount(withAccount)
|
||||
const message = ethUtil.removeHexPrefix(data)
|
||||
var privKey = wallet.getPrivateKey()
|
||||
var msgSig = ethUtil.ecsign(new Buffer(message, 'hex'), privKey)
|
||||
var rawMsgSig = ethUtil.bufferToHex(sigUtil.concatSig(msgSig.v, msgSig.r, msgSig.s))
|
||||
return rawMsgSig
|
||||
}
|
||||
|
||||
getWalletForAccount(account) {
|
||||
return this.wallets.find(w => w.getAddress().toString('hex') === account)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ module.exports = class MetamaskController {
|
||||
// forward directly to keyringController
|
||||
createNewVault: keyringController.createNewVault.bind(keyringController),
|
||||
addNewKeyring: keyringController.addNewKeyring.bind(keyringController),
|
||||
addNewAccount: keyringController.addNewAccount.bind(keyringController),
|
||||
submitPassword: keyringController.submitPassword.bind(keyringController),
|
||||
setSelectedAddress: keyringController.setSelectedAddress.bind(keyringController),
|
||||
approveTransaction: keyringController.approveTransaction.bind(keyringController),
|
||||
|
File diff suppressed because one or more lines are too long
39
development/states/first-time.json
Normal file
39
development/states/first-time.json
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"metamask": {
|
||||
"isInitialized": false,
|
||||
"isUnlocked": false,
|
||||
"rpcTarget": "https://rawtestrpc.metamask.io/",
|
||||
"identities": {},
|
||||
"unconfTxs": {},
|
||||
"currentFiat": "USD",
|
||||
"conversionRate": 11.47635827,
|
||||
"conversionDate": 1477606503,
|
||||
"network": null,
|
||||
"accounts": {},
|
||||
"transactions": [],
|
||||
"isConfirmed": true,
|
||||
"unconfMsgs": {},
|
||||
"messages": [],
|
||||
"shapeShiftTxList": [],
|
||||
"keyringTypes": [
|
||||
"Simple Key Pair"
|
||||
],
|
||||
"provider": {
|
||||
"type": "testnet"
|
||||
}
|
||||
},
|
||||
"appState": {
|
||||
"menuOpen": false,
|
||||
"currentView": {
|
||||
"name": "accounts",
|
||||
"detailView": null
|
||||
},
|
||||
"accountDetail": {
|
||||
"subview": "transactions"
|
||||
},
|
||||
"transForward": true,
|
||||
"isLoading": false,
|
||||
"warning": null
|
||||
},
|
||||
"identities": {}
|
||||
}
|
@ -34,6 +34,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "^1.5.2",
|
||||
"bip39": "^2.2.0",
|
||||
"browserify-derequire": "^0.9.4",
|
||||
"clone": "^1.0.2",
|
||||
"copy-to-clipboard": "^2.0.0",
|
||||
@ -55,7 +56,7 @@
|
||||
"iframe": "^1.0.0",
|
||||
"iframe-stream": "^1.0.2",
|
||||
"inject-css": "^0.1.1",
|
||||
"jazzicon": "^1.1.3",
|
||||
"jazzicon": "^1.2.0",
|
||||
"menu-droppo": "^1.1.0",
|
||||
"metamask-logo": "^2.1.2",
|
||||
"mississippi": "^1.2.0",
|
||||
|
91
test/unit/idStore-migration-test.js
Normal file
91
test/unit/idStore-migration-test.js
Normal file
@ -0,0 +1,91 @@
|
||||
const async = require('async')
|
||||
const assert = require('assert')
|
||||
const ethUtil = require('ethereumjs-util')
|
||||
const BN = ethUtil.BN
|
||||
const configManagerGen = require('../lib/mock-config-manager')
|
||||
const delegateCallCode = require('../lib/example-code.json').delegateCallCode
|
||||
|
||||
// The old way:
|
||||
const IdentityStore = require('../../app/scripts/lib/idStore')
|
||||
|
||||
// The new ways:
|
||||
var KeyringController = require('../../app/scripts/keyring-controller')
|
||||
const mockEncryptor = require('../lib/mock-encryptor')
|
||||
const MockSimpleKeychain = require('../lib/mock-simple-keychain')
|
||||
const sinon = require('sinon')
|
||||
|
||||
const mockVault = {
|
||||
seed: 'picnic injury awful upper eagle junk alert toss flower renew silly vague',
|
||||
account: '0x5d8de92c205279c10e5669f797b853ccef4f739a',
|
||||
}
|
||||
|
||||
describe('IdentityStore to KeyringController migration', function() {
|
||||
|
||||
// The stars of the show:
|
||||
let idStore, keyringController, seedWords
|
||||
|
||||
let password = 'password123'
|
||||
let entropy = 'entripppppyy duuude'
|
||||
let accounts = []
|
||||
let newAccounts = []
|
||||
let originalKeystore
|
||||
|
||||
// This is a lot of setup, I know!
|
||||
// We have to create an old style vault, populate it,
|
||||
// and THEN create a new one, before we can run tests on it.
|
||||
beforeEach(function(done) {
|
||||
this.sinon = sinon.sandbox.create()
|
||||
window.localStorage = {} // Hacking localStorage support into JSDom
|
||||
var configManager = configManagerGen()
|
||||
|
||||
window.localStorage = {} // Hacking localStorage support into JSDom
|
||||
|
||||
idStore = new IdentityStore({
|
||||
configManager: configManagerGen(),
|
||||
ethStore: {
|
||||
addAccount(acct) { accounts.push(ethUtil.addHexPrefix(acct)) },
|
||||
del(acct) { delete accounts[acct] },
|
||||
},
|
||||
})
|
||||
|
||||
idStore._createVault(password, mockVault.seed, null, function (err, seeds) {
|
||||
assert.ifError(err, 'createNewVault threw error')
|
||||
originalKeystore = idStore._idmgmt.keyStore
|
||||
|
||||
idStore.setLocked(function(err) {
|
||||
assert.ifError(err, 'createNewVault threw error')
|
||||
keyringController = new KeyringController({
|
||||
configManager,
|
||||
ethStore: {
|
||||
addAccount(acct) { newAccounts.push(ethUtil.addHexPrefix(acct)) },
|
||||
},
|
||||
})
|
||||
|
||||
// Stub out the browser crypto for a mock encryptor.
|
||||
// Browser crypto is tested in the integration test suite.
|
||||
keyringController.encryptor = mockEncryptor
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('creating new vault type', function() {
|
||||
it('should use the password to migrate the old vault', function(done) {
|
||||
keyringController.createNewVault(password, null, function (err, state) {
|
||||
assert.ifError(err, 'createNewVault threw error')
|
||||
|
||||
let newAccounts = keyringController.getAccounts()
|
||||
let newAccount = ethUtil.addHexPrefix(newAccounts[0])
|
||||
assert.equal(newAccount, accounts[0], 'restored the account')
|
||||
assert.equal(newAccount, mockVault.account, 'restored the correct account')
|
||||
|
||||
const newSeed = keyringController.keyrings[0].mnemonic
|
||||
assert.equal(newSeed, mockVault.seed, 'seed phrase transferred.')
|
||||
|
||||
assert(configManager.getVault(), 'new type of vault is persisted')
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
97
test/unit/keyrings/hd-test.js
Normal file
97
test/unit/keyrings/hd-test.js
Normal file
@ -0,0 +1,97 @@
|
||||
const assert = require('assert')
|
||||
const extend = require('xtend')
|
||||
const HdKeyring = require('../../../app/scripts/keyrings/hd')
|
||||
|
||||
// Sample account:
|
||||
const privKeyHex = 'b8a9c05beeedb25df85f8d641538cbffedf67216048de9c678ee26260eb91952'
|
||||
|
||||
const sampleMnemonic = 'finish oppose decorate face calm tragic certain desk hour urge dinosaur mango'
|
||||
const firstAcct = '1c96099350f13d558464ec79b9be4445aa0ef579'
|
||||
const secondAcct = '1b00aed43a693f3a957f9feb5cc08afa031e37a0'
|
||||
|
||||
describe('simple-keyring', function() {
|
||||
|
||||
let keyring
|
||||
beforeEach(function() {
|
||||
keyring = new HdKeyring()
|
||||
})
|
||||
|
||||
describe('Keyring.type()', function() {
|
||||
it('is a class method that returns the type string.', function() {
|
||||
const type = HdKeyring.type()
|
||||
assert.equal(typeof type, 'string')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#type', function() {
|
||||
it('returns the correct value', function() {
|
||||
const type = keyring.type
|
||||
const correct = HdKeyring.type()
|
||||
assert.equal(type, correct)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#serialize empty wallets.', function() {
|
||||
it('serializes a new mnemonic', function() {
|
||||
const output = keyring.serialize()
|
||||
assert.equal(output.n, 0)
|
||||
assert.equal(output.mnemonic, null)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#deserialize a private key', function() {
|
||||
it('serializes what it deserializes', function() {
|
||||
keyring.deserialize({
|
||||
mnemonic: sampleMnemonic,
|
||||
n: 1
|
||||
})
|
||||
assert.equal(keyring.wallets.length, 1, 'restores two accounts')
|
||||
keyring.addAccounts(1)
|
||||
|
||||
const accounts = keyring.getAccounts()
|
||||
assert.equal(accounts[0], firstAcct)
|
||||
assert.equal(accounts[1], secondAcct)
|
||||
assert.equal(accounts.length, 2)
|
||||
|
||||
const serialized = keyring.serialize()
|
||||
assert.equal(serialized.mnemonic, sampleMnemonic)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#addAccounts', function() {
|
||||
describe('with no arguments', function() {
|
||||
it('creates a single wallet', function() {
|
||||
keyring.addAccounts()
|
||||
assert.equal(keyring.wallets.length, 1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a numeric argument', function() {
|
||||
it('creates that number of wallets', function() {
|
||||
keyring.addAccounts(3)
|
||||
assert.equal(keyring.wallets.length, 3)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getAccounts', function() {
|
||||
it('calls getAddress on each wallet', function() {
|
||||
|
||||
// Push a mock wallet
|
||||
const desiredOutput = 'foo'
|
||||
keyring.wallets.push({
|
||||
getAddress() {
|
||||
return {
|
||||
toString() {
|
||||
return desiredOutput
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const output = keyring.getAccounts()
|
||||
assert.equal(output[0], desiredOutput)
|
||||
assert.equal(output.length, 1)
|
||||
})
|
||||
})
|
||||
})
|
@ -87,7 +87,7 @@ AccountsScreen.prototype.render = function () {
|
||||
h('div.footer.hover-white.pointer', {
|
||||
key: 'reveal-account-bar',
|
||||
onClick: () => {
|
||||
this.addNewKeyring()
|
||||
this.addNewAccount()
|
||||
},
|
||||
style: {
|
||||
display: 'flex',
|
||||
@ -146,8 +146,8 @@ AccountsScreen.prototype.onShowDetail = function (address, event) {
|
||||
this.props.dispatch(actions.showAccountDetail(address))
|
||||
}
|
||||
|
||||
AccountsScreen.prototype.addNewKeyring = function () {
|
||||
this.props.dispatch(actions.addNewKeyring('Simple Key Pair'))
|
||||
AccountsScreen.prototype.addNewAccount = function () {
|
||||
this.props.dispatch(actions.addNewAccount(0))
|
||||
}
|
||||
|
||||
AccountsScreen.prototype.goHome = function () {
|
||||
|
@ -25,7 +25,8 @@ var actions = {
|
||||
showInitializeMenu: showInitializeMenu,
|
||||
createNewVault: createNewVault,
|
||||
createNewVaultInProgress: createNewVaultInProgress,
|
||||
addNewKeyring: addNewKeyring,
|
||||
addNewKeyring,
|
||||
addNewAccount,
|
||||
showNewVaultSeed: showNewVaultSeed,
|
||||
showInfoPage: showInfoPage,
|
||||
// unlock screen
|
||||
@ -178,6 +179,7 @@ function createNewVault (password, entropy) {
|
||||
if (err) {
|
||||
return dispatch(actions.showWarning(err.message))
|
||||
}
|
||||
|
||||
dispatch(this.updateMetamaskState(newState))
|
||||
dispatch(this.showAccountsPage())
|
||||
dispatch(this.hideLoadingIndication())
|
||||
@ -199,6 +201,19 @@ function addNewKeyring (type, opts) {
|
||||
}
|
||||
}
|
||||
|
||||
function addNewAccount (ringNumber = 0) {
|
||||
return (dispatch) => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
background.addNewAccount(ringNumber, (err, newState) => {
|
||||
dispatch(this.hideLoadingIndication())
|
||||
if (err) {
|
||||
return dispatch(actions.showWarning(err))
|
||||
}
|
||||
dispatch(this.updateMetamaskState(newState))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function showInfoPage () {
|
||||
return {
|
||||
type: actions.SHOW_INFO_PAGE,
|
||||
|
@ -16,8 +16,8 @@ function IdenticonComponent () {
|
||||
}
|
||||
|
||||
IdenticonComponent.prototype.render = function () {
|
||||
var state = this.props
|
||||
var diameter = state.diameter || this.defaultDiameter
|
||||
var props = this.props
|
||||
var diameter = props.diameter || this.defaultDiameter
|
||||
return (
|
||||
h('div', {
|
||||
key: 'identicon-' + this.props.address,
|
||||
@ -33,15 +33,14 @@ IdenticonComponent.prototype.render = function () {
|
||||
}
|
||||
|
||||
IdenticonComponent.prototype.componentDidMount = function () {
|
||||
var state = this.props
|
||||
var address = state.address
|
||||
var props = this.props
|
||||
var address = props.address
|
||||
|
||||
if (!address) return
|
||||
|
||||
var container = findDOMNode(this)
|
||||
var diameter = state.diameter || this.defaultDiameter
|
||||
var imageify = state.imageify === undefined ? true : state.imageify
|
||||
var img = iconFactory.iconForAddress(address, diameter, imageify)
|
||||
var diameter = props.diameter || this.defaultDiameter
|
||||
var img = iconFactory.iconForAddress(address, diameter, false)
|
||||
container.appendChild(img)
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,8 @@ const connect = require('react-redux').connect
|
||||
const h = require('react-hyperscript')
|
||||
const Mascot = require('../components/mascot')
|
||||
const actions = require('../actions')
|
||||
const Tooltip = require('../components/tooltip')
|
||||
const getCaretCoordinates = require('textarea-caret')
|
||||
|
||||
module.exports = connect(mapStateToProps)(InitializeMenuScreen)
|
||||
|
||||
@ -54,18 +56,73 @@ InitializeMenuScreen.prototype.renderMenu = function () {
|
||||
},
|
||||
}, 'MetaMask'),
|
||||
|
||||
|
||||
h('div', [
|
||||
h('h3', {
|
||||
style: {
|
||||
fontSize: '0.8em',
|
||||
color: '#7F8082',
|
||||
display: 'inline',
|
||||
},
|
||||
}, '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',
|
||||
},
|
||||
}),
|
||||
]),
|
||||
]),
|
||||
|
||||
// password
|
||||
h('input.large-input.letter-spacey', {
|
||||
type: 'password',
|
||||
id: 'password-box',
|
||||
placeholder: 'New Password (min 8 chars)',
|
||||
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.showCreateVault.bind(this),
|
||||
onClick: this.createNewVault.bind(this),
|
||||
style: {
|
||||
margin: 12,
|
||||
},
|
||||
}, 'Create New Vault'),
|
||||
}, 'Create'),
|
||||
|
||||
/*
|
||||
h('.flex-row.flex-center.flex-grow', [
|
||||
h('hr'),
|
||||
h('div', 'Advanced (Eventually?)'),
|
||||
h('hr'),
|
||||
h('p.pointer', {
|
||||
style: {
|
||||
fontSize: '0.8em',
|
||||
color: 'rgb(247, 134, 28)',
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
}, 'I already have a DEN that I would like to import'),
|
||||
]),
|
||||
*/
|
||||
|
||||
@ -73,7 +130,42 @@ InitializeMenuScreen.prototype.renderMenu = function () {
|
||||
)
|
||||
}
|
||||
|
||||
InitializeMenuScreen.prototype.showCreateVault = function () {
|
||||
this.props.dispatch(actions.showCreateVault())
|
||||
InitializeMenuScreen.prototype.createVaultOnEnter = function (event) {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault()
|
||||
this.createNewVault()
|
||||
}
|
||||
}
|
||||
|
||||
InitializeMenuScreen.prototype.createNewVault = function () {
|
||||
var passwordBox = document.getElementById('password-box')
|
||||
var password = passwordBox.value
|
||||
var passwordConfirmBox = document.getElementById('password-box-confirm')
|
||||
var passwordConfirm = passwordConfirmBox.value
|
||||
// var entropy = document.getElementById('entropy-text-entry').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
|
||||
}
|
||||
|
||||
this.props.dispatch(actions.createNewVault(password, ''/* entropy*/))
|
||||
}
|
||||
|
||||
InitializeMenuScreen.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,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -104,6 +104,3 @@ UnlockScreen.prototype.inputChanged = function (event) {
|
||||
})
|
||||
}
|
||||
|
||||
UnlockScreen.prototype.emitAnim = function (name, a, b, c) {
|
||||
this.animationEventEmitter.emit(name, a, b, c)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user