diff options
Merge pull request #73 from MetaMask/Bip44
Bip44-compliant HD Tree Generation
Diffstat (limited to 'app/scripts')
-rw-r--r-- | app/scripts/lib/idStore.js | 126 |
1 files changed, 60 insertions, 66 deletions
diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js index c4547b07f..e3f2a841d 100644 --- a/app/scripts/lib/idStore.js +++ b/app/scripts/lib/idStore.js @@ -14,23 +14,24 @@ module.exports = IdentityStore inherits(IdentityStore, EventEmitter) function IdentityStore(ethStore) { - const self = this - EventEmitter.call(self) + EventEmitter.call(this) // we just use the ethStore to auto-add accounts - self._ethStore = ethStore + this._ethStore = ethStore // lightwallet key store - self._keyStore = null + this._keyStore = null // lightwallet wrapper - self._idmgmt = null + this._idmgmt = null - self._currentState = { + this.hdPathString = "m/44'/60'/0'/0" + + this._currentState = { selectedAddress: null, identities: {}, unconfTxs: {}, } // not part of serilized metamask state - only kept in memory - self._unconfTxCbs = {} + this._unconfTxCbs = {} } // @@ -51,18 +52,17 @@ IdentityStore.prototype.createNewVault = function(password, entropy, cb){ } IdentityStore.prototype.recoverFromSeed = function(password, seed, cb){ - const self = this - self._createIdmgmt(password, seed, null, function(err){ + this._createIdmgmt(password, seed, null, (err) => { if (err) return cb(err) - self._loadIdentities() - self._didUpdate() + + this._loadIdentities() + this._didUpdate() cb() }) } IdentityStore.prototype.setStore = function(store){ - const self = this - self._ethStore = store + this._ethStore = store } IdentityStore.prototype.clearSeedWordCache = function(cb) { @@ -71,46 +71,40 @@ IdentityStore.prototype.clearSeedWordCache = function(cb) { } IdentityStore.prototype.getState = function(){ - const self = this const cachedSeeds = window.localStorage['seedWords'] - return clone(extend(self._currentState, { + return clone(extend(this._currentState, { isInitialized: !!window.localStorage['lightwallet'] && !cachedSeeds, - isUnlocked: self._isUnlocked(), + isUnlocked: this._isUnlocked(), seedWords: cachedSeeds, })) } IdentityStore.prototype.getSelectedAddress = function(){ - const self = this - return self._currentState.selectedAddress + return this._currentState.selectedAddress } IdentityStore.prototype.setSelectedAddress = function(address){ - const self = this - self._currentState.selectedAddress = address - self._didUpdate() + this._currentState.selectedAddress = address + this._didUpdate() } IdentityStore.prototype.setLocked = function(cb){ - const self = this - delete self._keyStore - delete self._idmgmt + delete this._keyStore + delete this._idmgmt cb() } IdentityStore.prototype.submitPassword = function(password, cb){ - const self = this - self._tryPassword(password, function(err){ + this._tryPassword(password, (err) => { if (err) return cb(err) // load identities before returning... - self._loadIdentities() + this._loadIdentities() cb() }) } // comes from dapp via zero-client hooked-wallet provider IdentityStore.prototype.addUnconfirmedTransaction = function(txParams, cb){ - var self = this // create txData obj with parameters and meta data var time = (new Date()).getTime() @@ -121,56 +115,51 @@ IdentityStore.prototype.addUnconfirmedTransaction = function(txParams, cb){ time: time, status: 'unconfirmed', } - self._currentState.unconfTxs[txId] = txData + this._currentState.unconfTxs[txId] = txData console.log('addUnconfirmedTransaction:', txData) // keep the cb around for after approval (requires user interaction) - self._unconfTxCbs[txId] = cb + this._unconfTxCbs[txId] = cb // signal update - self._didUpdate() + this._didUpdate() return txId } // comes from metamask ui IdentityStore.prototype.approveTransaction = function(txId, cb){ - const self = this - - var txData = self._currentState.unconfTxs[txId] + var txData = this._currentState.unconfTxs[txId] var txParams = txData.txParams - var approvalCb = self._unconfTxCbs[txId] || noop + var approvalCb = this._unconfTxCbs[txId] || noop // accept tx cb() approvalCb(null, true) // clean up - delete self._currentState.unconfTxs[txId] - delete self._unconfTxCbs[txId] - self._didUpdate() + delete this._currentState.unconfTxs[txId] + delete this._unconfTxCbs[txId] + this._didUpdate() } // comes from metamask ui IdentityStore.prototype.cancelTransaction = function(txId){ - const self = this - - var txData = self._currentState.unconfTxs[txId] - var approvalCb = self._unconfTxCbs[txId] || noop + var txData = this._currentState.unconfTxs[txId] + var approvalCb = this._unconfTxCbs[txId] || noop // reject tx approvalCb(null, false) // clean up - delete self._currentState.unconfTxs[txId] - delete self._unconfTxCbs[txId] - self._didUpdate() + delete this._currentState.unconfTxs[txId] + delete this._unconfTxCbs[txId] + this._didUpdate() } // performs the actual signing, no autofill of params IdentityStore.prototype.signTransaction = function(txParams, cb){ - const self = this try { console.log('signing tx...', txParams) - var rawTx = self._idmgmt.signTx(txParams) + var rawTx = this._idmgmt.signTx(txParams) cb(null, rawTx) } catch (err) { cb(err) @@ -182,13 +171,11 @@ IdentityStore.prototype.signTransaction = function(txParams, cb){ // IdentityStore.prototype._didUpdate = function(){ - const self = this - self.emit('update', self.getState()) + this.emit('update', this.getState()) } IdentityStore.prototype._isUnlocked = function(){ - const self = this - var result = Boolean(self._keyStore) && Boolean(self._idmgmt) + var result = Boolean(this._keyStore) && Boolean(this._idmgmt) return result } @@ -198,22 +185,21 @@ IdentityStore.prototype._cacheSeedWordsUntilConfirmed = function(seedWords) { // load identities from keyStoreet IdentityStore.prototype._loadIdentities = function(){ - const self = this - if (!self._isUnlocked()) throw new Error('not unlocked') + if (!this._isUnlocked()) throw new Error('not unlocked') // get addresses and normalize address hexString - var addresses = self._keyStore.getAddresses().map(function(address){ return '0x'+address }) - addresses.forEach(function(address){ + var addresses = this._keyStore.getAddresses(this.hdPathString).map((address) => { return '0x'+address }) + addresses.forEach((address) => { // // add to ethStore - self._ethStore.addAccount(address) + this._ethStore.addAccount(address) // add to identities var identity = { name: 'Wally', img: 'QmW6hcwYzXrNkuHrpvo58YeZvbZxUddv69ATSHY3BHpPdd', address: address, } - self._currentState.identities[address] = identity + this._currentState.identities[address] = identity }) - self._didUpdate() + this._didUpdate() } // @@ -221,8 +207,7 @@ IdentityStore.prototype._loadIdentities = function(){ // IdentityStore.prototype._tryPassword = function(password, cb){ - const self = this - self._createIdmgmt(password, null, null, cb) + this._createIdmgmt(password, null, null, cb) } IdentityStore.prototype._createIdmgmt = function(password, seed, entropy, cb){ @@ -232,7 +217,7 @@ IdentityStore.prototype._createIdmgmt = function(password, seed, entropy, cb){ var serializedKeystore = window.localStorage['lightwallet'] if (seed) { - this._restoreFromSeed(keyStore, seed, derivedKey) + keyStore = this._restoreFromSeed(password, seed, derivedKey) // returning user, recovering from localStorage } else if (serializedKeystore) { @@ -249,17 +234,22 @@ IdentityStore.prototype._createIdmgmt = function(password, seed, entropy, cb){ this._idmgmt = new IdManagement({ keyStore: keyStore, derivedKey: derivedKey, + hdPathSTring: this.hdPathString, }) cb() }) } -IdentityStore.prototype._restoreFromSeed = function(keyStore, seed, derivedKey) { - keyStore = new LightwalletKeyStore(seed, derivedKey) +IdentityStore.prototype._restoreFromSeed = function(password, seed, derivedKey) { + var keyStore = new LightwalletKeyStore(seed, derivedKey, this.hdPathString) + keyStore.addHdDerivationPath(this.hdPathString, derivedKey, {curve: 'secp256k1', purpose: 'sign'}); + keyStore.setDefaultHdDerivationPath(this.hdPathString) + keyStore.generateNewAddress(derivedKey, 3) window.localStorage['lightwallet'] = keyStore.serialize() console.log('restored from seed. saved to keystore localStorage') + return keyStore } IdentityStore.prototype._loadFromLocalStorage = function(serializedKeystore, derivedKey) { @@ -268,19 +258,23 @@ IdentityStore.prototype._loadFromLocalStorage = function(serializedKeystore, der IdentityStore.prototype._createFirstWallet = function(entropy, derivedKey) { var secretSeed = LightwalletKeyStore.generateRandomSeed(entropy) - var keyStore = new LightwalletKeyStore(secretSeed, derivedKey) + var keyStore = new LightwalletKeyStore(secretSeed, derivedKey, this.hdPathString) + keyStore.addHdDerivationPath(this.hdPathString, derivedKey, {curve: 'secp256k1', purpose: 'sign'}); + keyStore.setDefaultHdDerivationPath(this.hdPathString) + keyStore.generateNewAddress(derivedKey, 3) window.localStorage['lightwallet'] = keyStore.serialize() console.log('saved to keystore localStorage') return keyStore } -function IdManagement( opts = { keyStore: null, derivedKey: null } ) { +function IdManagement( opts = { keyStore: null, derivedKey: null, hdPathString: null } ) { this.keyStore = opts.keyStore this.derivedKey = opts.derivedKey + this.hdPathString = opts.hdPathString this.getAddresses = function(){ - return keyStore.getAddresses().map(function(address){ return '0x'+address }) + return keyStore.getAddresses(this.hdPathString).map(function(address){ return '0x'+address }) } this.signTx = function(txParams){ |