mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-22 17:33:23 +01:00
Add seed word caching during confirmation screen
In order to persist the seed word page until the user clicks the confirmation button, we need to store the seed words in localStorage. To simplify this process I've also reorganized some of the account manager code, broken up one large function into many smaller functions, and created a new class for the IdMgmt object. Again, sorry such a big refactor in one commit, but I really had to break it down to work through it.
This commit is contained in:
parent
84789d674a
commit
55f8ae4edd
1
app/images/loading.svg
Normal file
1
app/images/loading.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg width='120px' height='120px' xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" class="uil-default"><rect x="0" y="0" width="100" height="100" fill="none" class="bk"></rect><rect x='46' y='39' width='8' height='22' rx='5' ry='5' fill='#ffae29' transform='rotate(0 50 50) translate(0 -20)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0s' repeatCount='indefinite'/></rect><rect x='46' y='39' width='8' height='22' rx='5' ry='5' fill='#ffae29' transform='rotate(40 50 50) translate(0 -20)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.1111111111111111s' repeatCount='indefinite'/></rect><rect x='46' y='39' width='8' height='22' rx='5' ry='5' fill='#ffae29' transform='rotate(80 50 50) translate(0 -20)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.2222222222222222s' repeatCount='indefinite'/></rect><rect x='46' y='39' width='8' height='22' rx='5' ry='5' fill='#ffae29' transform='rotate(120 50 50) translate(0 -20)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.3333333333333333s' repeatCount='indefinite'/></rect><rect x='46' y='39' width='8' height='22' rx='5' ry='5' fill='#ffae29' transform='rotate(160 50 50) translate(0 -20)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.4444444444444444s' repeatCount='indefinite'/></rect><rect x='46' y='39' width='8' height='22' rx='5' ry='5' fill='#ffae29' transform='rotate(200 50 50) translate(0 -20)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.5555555555555556s' repeatCount='indefinite'/></rect><rect x='46' y='39' width='8' height='22' rx='5' ry='5' fill='#ffae29' transform='rotate(240 50 50) translate(0 -20)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.6666666666666666s' repeatCount='indefinite'/></rect><rect x='46' y='39' width='8' height='22' rx='5' ry='5' fill='#ffae29' transform='rotate(280 50 50) translate(0 -20)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.7777777777777778s' repeatCount='indefinite'/></rect><rect x='46' y='39' width='8' height='22' rx='5' ry='5' fill='#ffae29' transform='rotate(320 50 50) translate(0 -20)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.8888888888888888s' repeatCount='indefinite'/></rect></svg>
|
After Width: | Height: | Size: 2.3 KiB |
@ -121,10 +121,11 @@ function linkDnode(stream){
|
||||
approveTransaction: idStore.approveTransaction.bind(idStore),
|
||||
cancelTransaction: idStore.cancelTransaction.bind(idStore),
|
||||
setLocked: idStore.setLocked.bind(idStore),
|
||||
clearSeedWordCache: idStore.clearSeedWordCache.bind(idStore),
|
||||
})
|
||||
stream.pipe(connection).pipe(stream)
|
||||
connection.on('remote', function(remote){
|
||||
|
||||
|
||||
// push updates to popup
|
||||
ethStore.on('update', sendUpdate)
|
||||
idStore.on('update', sendUpdate)
|
||||
@ -208,4 +209,4 @@ function jsonStringifyStream(){
|
||||
})
|
||||
}
|
||||
|
||||
function noop(){}
|
||||
function noop(){}
|
||||
|
@ -37,22 +37,22 @@ function IdentityStore(ethStore) {
|
||||
// public
|
||||
//
|
||||
|
||||
IdentityStore.prototype.createNewVault = function(password, cb){
|
||||
const self = this
|
||||
delete self._keyStore
|
||||
IdentityStore.prototype.createNewVault = function(password, entropy, cb){
|
||||
delete this._keyStore
|
||||
delete window.localStorage['lightwallet']
|
||||
var keyStore = self._createIdmgmt(password, null, function(err){
|
||||
this._createIdmgmt(password, null, entropy, (err) => {
|
||||
if (err) return cb(err)
|
||||
var seedWords = self._idmgmt.getSeed()
|
||||
self._loadIdentities()
|
||||
self._didUpdate()
|
||||
var seedWords = this._idmgmt.getSeed()
|
||||
this._cacheSeedWordsUntilConfirmed(seedWords)
|
||||
this._loadIdentities()
|
||||
this._didUpdate()
|
||||
cb(null, seedWords)
|
||||
})
|
||||
}
|
||||
|
||||
IdentityStore.prototype.recoverFromSeed = function(password, seed, cb){
|
||||
const self = this
|
||||
self._createIdmgmt(password, seed, function(err){
|
||||
self._createIdmgmt(password, seed, null, function(err){
|
||||
if (err) return cb(err)
|
||||
self._loadIdentities()
|
||||
self._didUpdate()
|
||||
@ -65,12 +65,18 @@ IdentityStore.prototype.setStore = function(store){
|
||||
self._ethStore = store
|
||||
}
|
||||
|
||||
IdentityStore.prototype.clearSeedWordCache = function(cb) {
|
||||
delete window.localStorage['seedWords']
|
||||
cb()
|
||||
}
|
||||
|
||||
IdentityStore.prototype.getState = function(){
|
||||
const self = this
|
||||
const cachedSeeds = window.localStorage['seedWords']
|
||||
return clone(extend(self._currentState, {
|
||||
isInitialized: !!window.localStorage['lightwallet'],
|
||||
isInitialized: !!window.localStorage['lightwallet'] && !cachedSeeds,
|
||||
isUnlocked: self._isUnlocked(),
|
||||
seedWords: cachedSeeds,
|
||||
}))
|
||||
}
|
||||
|
||||
@ -185,6 +191,10 @@ IdentityStore.prototype._isUnlocked = function(){
|
||||
return result
|
||||
}
|
||||
|
||||
IdentityStore.prototype._cacheSeedWordsUntilConfirmed = function(seedWords) {
|
||||
window.localStorage['seedWords'] = seedWords
|
||||
}
|
||||
|
||||
// load identities from keyStoreet
|
||||
IdentityStore.prototype._loadIdentities = function(){
|
||||
const self = this
|
||||
@ -211,59 +221,86 @@ IdentityStore.prototype._loadIdentities = function(){
|
||||
|
||||
IdentityStore.prototype._tryPassword = function(password, cb){
|
||||
const self = this
|
||||
self._createIdmgmt(password, null, cb)
|
||||
self._createIdmgmt(password, null, null, cb)
|
||||
}
|
||||
|
||||
IdentityStore.prototype._createIdmgmt = function(password, seed, cb){
|
||||
const self = this
|
||||
IdentityStore.prototype._createIdmgmt = function(password, seed, entropy, cb){
|
||||
var keyStore = null
|
||||
LightwalletKeyStore.deriveKeyFromPassword(password, function(err, derrivedKey){
|
||||
LightwalletKeyStore.deriveKeyFromPassword(password, (err, derivedKey) => {
|
||||
if (err) return cb(err)
|
||||
var serializedKeystore = window.localStorage['lightwallet']
|
||||
// recovering from seed
|
||||
|
||||
if (seed) {
|
||||
keyStore = new LightwalletKeyStore(seed, derrivedKey)
|
||||
keyStore.generateNewAddress(derrivedKey, 3)
|
||||
window.localStorage['lightwallet'] = keyStore.serialize()
|
||||
console.log('saved to keystore localStorage')
|
||||
this._restoreFromSeed(keyStore, seed, derivedKey)
|
||||
|
||||
// returning user, recovering from localStorage
|
||||
} else if (serializedKeystore) {
|
||||
keyStore = LightwalletKeyStore.deserialize(serializedKeystore)
|
||||
var isCorrect = keyStore.isDerivedKeyCorrect(derrivedKey)
|
||||
keyStore = this._loadFromLocalStorage(serializedKeystore, derivedKey, cb)
|
||||
var isCorrect = keyStore.isDerivedKeyCorrect(derivedKey)
|
||||
if (!isCorrect) return cb(new Error('Lightwallet - password incorrect'))
|
||||
// first time here
|
||||
|
||||
// first time here
|
||||
} else {
|
||||
var secretSeed = LightwalletKeyStore.generateRandomSeed()
|
||||
keyStore = new LightwalletKeyStore(secretSeed, derrivedKey)
|
||||
keyStore.generateNewAddress(derrivedKey, 3)
|
||||
window.localStorage['lightwallet'] = keyStore.serialize()
|
||||
console.log('saved to keystore localStorage')
|
||||
}
|
||||
self._keyStore = keyStore
|
||||
self._idmgmt = {
|
||||
getAddresses: function(){
|
||||
return keyStore.getAddresses().map(function(address){ return '0x'+address })
|
||||
},
|
||||
signTx: function(txParams){
|
||||
// normalize values
|
||||
txParams.to = ethUtil.addHexPrefix(txParams.to)
|
||||
txParams.from = ethUtil.addHexPrefix(txParams.from)
|
||||
txParams.value = ethUtil.addHexPrefix(txParams.value)
|
||||
txParams.data = ethUtil.addHexPrefix(txParams.data)
|
||||
txParams.gasLimit = ethUtil.addHexPrefix(txParams.gasLimit || txParams.gas)
|
||||
txParams.nonce = ethUtil.addHexPrefix(txParams.nonce)
|
||||
var tx = new Transaction(txParams)
|
||||
var rawTx = '0x'+tx.serialize().toString('hex')
|
||||
return '0x'+LightwalletSigner.signTx(keyStore, derrivedKey, rawTx, txParams.from)
|
||||
},
|
||||
getSeed: function(){
|
||||
return keyStore.getSeed(derrivedKey)
|
||||
},
|
||||
keyStore = this._createFirstWallet(entropy, derivedKey)
|
||||
}
|
||||
|
||||
this._keyStore = keyStore
|
||||
this._idmgmt = new IdManagement({
|
||||
keyStore: keyStore,
|
||||
derivedKey: derivedKey,
|
||||
})
|
||||
|
||||
cb()
|
||||
})
|
||||
}
|
||||
|
||||
IdentityStore.prototype._restoreFromSeed = function(keyStore, seed, derivedKey) {
|
||||
keyStore = new LightwalletKeyStore(seed, derivedKey)
|
||||
keyStore.generateNewAddress(derivedKey, 3)
|
||||
window.localStorage['lightwallet'] = keyStore.serialize()
|
||||
console.log('restored from seed. saved to keystore localStorage')
|
||||
}
|
||||
|
||||
IdentityStore.prototype._loadFromLocalStorage = function(serializedKeystore, derivedKey) {
|
||||
return LightwalletKeyStore.deserialize(serializedKeystore)
|
||||
}
|
||||
|
||||
IdentityStore.prototype._createFirstWallet = function(entropy, derivedKey) {
|
||||
var secretSeed = LightwalletKeyStore.generateRandomSeed(entropy)
|
||||
var keyStore = new LightwalletKeyStore(secretSeed, derivedKey)
|
||||
keyStore.generateNewAddress(derivedKey, 3)
|
||||
window.localStorage['lightwallet'] = keyStore.serialize()
|
||||
console.log('wallet generated. saved to keystore localStorage')
|
||||
return keyStore
|
||||
}
|
||||
|
||||
function IdManagement( opts = { keyStore: null, derivedKey: null } ) {
|
||||
this.keyStore = opts.keyStore
|
||||
this.derivedKey = opts.derivedKey
|
||||
|
||||
this.getAddresses = function(){
|
||||
return keyStore.getAddresses().map(function(address){ return '0x'+address })
|
||||
}
|
||||
|
||||
this.signTx = function(txParams){
|
||||
// normalize values
|
||||
txParams.to = ethUtil.addHexPrefix(txParams.to)
|
||||
txParams.from = ethUtil.addHexPrefix(txParams.from)
|
||||
txParams.value = ethUtil.addHexPrefix(txParams.value)
|
||||
txParams.data = ethUtil.addHexPrefix(txParams.data)
|
||||
txParams.gasLimit = ethUtil.addHexPrefix(txParams.gasLimit || txParams.gas)
|
||||
txParams.nonce = ethUtil.addHexPrefix(txParams.nonce)
|
||||
var tx = new Transaction(txParams)
|
||||
var rawTx = '0x'+tx.serialize().toString('hex')
|
||||
return '0x'+LightwalletSigner.signTx(this.keyStore, this.derivedKey, rawTx, txParams.from)
|
||||
}
|
||||
|
||||
this.getSeed = function(){
|
||||
return this.keyStore.getSeed(this.derivedKey)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// util
|
||||
|
||||
function noop(){}
|
||||
|
Loading…
Reference in New Issue
Block a user