diff options
-rw-r--r-- | app/images/loading.svg | 1 | ||||
-rw-r--r-- | app/scripts/background.js | 5 | ||||
-rw-r--r-- | app/scripts/lib/idStore.js | 131 |
3 files changed, 88 insertions, 49 deletions
diff --git a/app/images/loading.svg b/app/images/loading.svg new file mode 100644 index 000000000..854da88dd --- /dev/null +++ b/app/images/loading.svg @@ -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>
\ No newline at end of file diff --git a/app/scripts/background.js b/app/scripts/background.js index aa06f27f1..1a0d36ef8 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -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(){}
\ No newline at end of file +function noop(){} diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js index 173a1672f..c44429216 100644 --- a/app/scripts/lib/idStore.js +++ b/app/scripts/lib/idStore.js @@ -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(){} |