From b2b3f4b26bbaaf978b454afe18e9116ac8a693d4 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 24 Jun 2016 15:52:56 -0700 Subject: Improve refactor Replace config-manager-singleton with one that is instantiated within the `background-controller`, and takes its persistence callbacks from its instantiated options. Replaced class getters with more familiar get___() functions. --- app/scripts/background-controller.js | 78 ++++++++++++++--------------- app/scripts/background.js | 62 +++++++++++++++++++++-- app/scripts/lib/config-manager-singleton.js | 3 -- app/scripts/lib/config-manager.js | 55 ++------------------ app/scripts/lib/id-management.js | 6 +-- app/scripts/lib/idStore.js | 25 +++++++-- 6 files changed, 124 insertions(+), 105 deletions(-) delete mode 100644 app/scripts/lib/config-manager-singleton.js (limited to 'app/scripts') diff --git a/app/scripts/background-controller.js b/app/scripts/background-controller.js index e5814e84c..bda9f41ac 100644 --- a/app/scripts/background-controller.js +++ b/app/scripts/background-controller.js @@ -2,19 +2,18 @@ const extend = require('xtend') const EthStore = require('eth-store') const MetaMaskProvider = require('web3-provider-engine/zero.js') const IdentityStore = require('./lib/idStore') -const configManager = require('./lib/config-manager-singleton') const messageManager = require('./lib/message-manager') const HostStore = require('./lib/remote-store.js').HostStore const Web3 = require('web3') - +const ConfigManager = require('./lib/config-manager') module.exports = BackgroundController class BackgroundController { constructor (opts) { - this.idStore = new IdentityStore() - this.configManager = configManager + this.configManager = new ConfigManager(opts) + this.idStore = new IdentityStore({ configManager }) this.messageManager = messageManager this.provider = this.initializeProvider(opts) this.ethStore = new EthStore(this.provider) @@ -22,7 +21,7 @@ class BackgroundController { this.publicConfigStore = this.initPublicConfigStore() } - get state () { + getState () { return extend( this.ethStore.getState(), this.idStore.getState(), @@ -30,15 +29,15 @@ class BackgroundController { ) } - get api () { + getApi () { const idStore = this.idStore return { - getState: function (cb) { cb(null, this.state) }, - setRpcTarget: setRpcTarget, - setProviderType: setProviderType, - useEtherscanProvider: useEtherscanProvider, - agreeToDisclaimer: agreeToDisclaimer, + getState: function (cb) { cb(null, this.getState()) }, + setRpcTarget: this.setRpcTarget.bind(this), + setProviderType: this.setProviderType.bind(this), + useEtherscanProvider: this.useEtherscanProvider.bind(this), + agreeToDisclaimer: this.agreeToDisclaimer.bind(this), // forward directly to idStore createNewVault: idStore.createNewVault.bind(idStore), recoverFromSeed: idStore.recoverFromSeed.bind(idStore), @@ -98,14 +97,14 @@ class BackgroundController { } sendUpdate () { - this.remote.sendUpdate(this.state) + this.remote.sendUpdate(this.getState()) } initializeProvider (opts) { const idStore = this.idStore var providerOpts = { - rpcUrl: configManager.getCurrentRpcAddress(), + rpcUrl: this.configManager.getCurrentRpcAddress(), // account mgmt getAccounts: function (cb) { var selectedAddress = idStore.getSelectedAddress() @@ -188,7 +187,7 @@ class BackgroundController { } } - newUnsignedMessage(msgParams, cb) { + newUnsignedMessage (msgParams, cb) { var state = this.idStore.getState() if (!state.isUnlocked) { this.opts.unlockAccountMessage() @@ -212,7 +211,7 @@ class BackgroundController { processBlock (block) { console.log(`BLOCK CHANGED: #${block.number.toString('hex')} 0x${block.hash.toString('hex')}`) this.verifyNetwork() - } + } verifyNetwork () { // Check network when restoring connectivity: @@ -220,36 +219,37 @@ class BackgroundController { this.idStore.getNetwork() } } -} -// config -// + // config + // -function agreeToDisclaimer (cb) { - try { - configManager.setConfirmed(true) - cb() - } catch (e) { - cb(e) + function agreeToDisclaimer (cb) { + try { + this.configManager.setConfirmed(true) + cb() + } catch (e) { + cb(e) + } } -} -// called from popup -function setRpcTarget (rpcTarget) { - configManager.setRpcTarget(rpcTarget) - chrome.runtime.reload() - idStore.getNetwork() -} + // called from popup + function setRpcTarget (rpcTarget) { + this.configManager.setRpcTarget(rpcTarget) + chrome.runtime.reload() + idStore.getNetwork() + } -function setProviderType (type) { - configManager.setProviderType(type) - chrome.runtime.reload() - idStore.getNetwork() -} + function setProviderType (type) { + this.configManager.setProviderType(type) + chrome.runtime.reload() + idStore.getNetwork() + } + + function useEtherscanProvider () { + this.configManager.useEtherscanProvider() + chrome.runtime.reload() + } -function useEtherscanProvider () { - configManager.useEtherscanProvider() - chrome.runtime.reload() } function noop () {} diff --git a/app/scripts/background.js b/app/scripts/background.js index d90b047e7..83d8d0258 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -5,16 +5,20 @@ const PortStream = require('./lib/port-stream.js') const createUnlockRequestNotification = require('./lib/notifications.js').createUnlockRequestNotification const createTxNotification = require('./lib/notifications.js').createTxNotification const createMsgNotification = require('./lib/notifications.js').createMsgNotification -const configManager = require('./lib/config-manager-singleton') const messageManager = require('./lib/message-manager') const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex - const BackgroundController = require('./background-controller') +const STORAGE_KEY = 'metamask-config' + const controller = new BackgroundController({ + // User confirmation callbacks: showUnconfirmedMessage, unlockAccountMessage, showUnconfirmedTx, + // Persistence Methods: + setData, + loadData, }) const idStore = controller.idStore @@ -82,7 +86,7 @@ function setupTrustedCommunication (connectionStream, originDomain) { function setupControllerConnection (stream) { controller.stream = stream - var api = controller.api + var api = controller.getApi() var dnode = Dnode(api) stream.pipe(dnode).pipe(stream) dnode.on('remote', function() { @@ -106,7 +110,7 @@ idStore.on('update', updateBadge) function updateBadge (state) { var label = '' - var unconfTxs = configManager.unconfirmedTxs() + var unconfTxs = controller.configManager.unconfirmedTxs() var unconfTxLen = Object.keys(unconfTxs).length var unconfMsgs = messageManager.unconfirmedMsgs() var unconfMsgLen = Object.keys(unconfMsgs).length @@ -118,4 +122,54 @@ function updateBadge (state) { chrome.browserAction.setBadgeBackgroundColor({ color: '#506F8B' }) } +function loadData () { + var oldData = getOldStyleData() + var newData + try { + newData = JSON.parse(window.localStorage[STORAGE_KEY]) + } catch (e) {} + + var data = extend({ + meta: { + version: 0, + }, + data: { + config: { + provider: { + type: 'testnet', + }, + }, + }, + }, oldData || null, newData || null) + return data +} + +function getOldStyleData () { + var config, wallet, seedWords + + var result = { + meta: { version: 0 }, + data: {}, + } + + try { + config = JSON.parse(window.localStorage['config']) + result.data.config = config + } catch (e) {} + try { + wallet = JSON.parse(window.localStorage['lightwallet']) + result.data.wallet = wallet + } catch (e) {} + try { + seedWords = window.localStorage['seedWords'] + result.data.seedWords = seedWords + } catch (e) {} + + return result +} + +function setData (data) { + window.localStorage[STORAGE_KEY] = JSON.stringify(data) +} + function noop () {} diff --git a/app/scripts/lib/config-manager-singleton.js b/app/scripts/lib/config-manager-singleton.js deleted file mode 100644 index 5915c401b..000000000 --- a/app/scripts/lib/config-manager-singleton.js +++ /dev/null @@ -1,3 +0,0 @@ -var ConfigManager = require('./config-manager') - -module.exports = new ConfigManager() diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index a3ff0bdfb..9793728bb 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -3,7 +3,6 @@ const extend = require('xtend') const MetamaskConfig = require('../config.js') const migrations = require('./migrations') -const STORAGE_KEY = 'metamask-config' const TESTNET_RPC = MetamaskConfig.network.testnet const MAINNET_RPC = MetamaskConfig.network.mainnet @@ -15,7 +14,7 @@ const MAINNET_RPC = MetamaskConfig.network.mainnet * particular portions of the state. */ module.exports = ConfigManager -function ConfigManager () { +function ConfigManager (opts) { // ConfigManager is observable and will emit updates this._subs = [] @@ -37,12 +36,10 @@ function ConfigManager () { // How to load initial config. // Includes step on migrating pre-pojo-migrator data. - loadData: loadData, + loadData: opts.loadData, // How to persist migrated config. - setData: function (data) { - window.localStorage[STORAGE_KEY] = JSON.stringify(data) - }, + setData: opts.setData, }) } @@ -280,49 +277,3 @@ ConfigManager.prototype.getConfirmed = function () { return ('isConfirmed' in data) && data.isConfirmed } -function loadData () { - var oldData = getOldStyleData() - var newData - try { - newData = JSON.parse(window.localStorage[STORAGE_KEY]) - } catch (e) {} - - var data = extend({ - meta: { - version: 0, - }, - data: { - config: { - provider: { - type: 'testnet', - }, - }, - }, - }, oldData || null, newData || null) - return data -} - -function getOldStyleData () { - var config, wallet, seedWords - - var result = { - meta: { version: 0 }, - data: {}, - } - - try { - config = JSON.parse(window.localStorage['config']) - result.data.config = config - } catch (e) {} - try { - wallet = JSON.parse(window.localStorage['lightwallet']) - result.data.wallet = wallet - } catch (e) {} - try { - seedWords = window.localStorage['seedWords'] - result.data.seedWords = seedWords - } catch (e) {} - - return result -} - diff --git a/app/scripts/lib/id-management.js b/app/scripts/lib/id-management.js index cc50bd649..9b8ceb415 100644 --- a/app/scripts/lib/id-management.js +++ b/app/scripts/lib/id-management.js @@ -1,6 +1,5 @@ const ethUtil = require('ethereumjs-util') const Transaction = require('ethereumjs-tx') -const configManager = require('./config-manager-singleton') module.exports = IdManagement @@ -9,6 +8,7 @@ function IdManagement (opts) { this.keyStore = opts.keyStore this.derivedKey = opts.derivedKey + this.configManager = opts.configManager this.hdPathString = "m/44'/60'/0'/0" this.getAddresses = function () { @@ -32,9 +32,9 @@ function IdManagement (opts) { // Add the tx hash to the persisted meta-tx object var txHash = ethUtil.bufferToHex(tx.hash()) - var metaTx = configManager.getTx(txParams.metamaskId) + var metaTx = this.configManager.getTx(txParams.metamaskId) metaTx.hash = txHash - configManager.updateTx(metaTx) + this.configManager.updateTx(metaTx) // return raw serialized tx var rawTx = ethUtil.bufferToHex(tx.serialize()) diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js index d9657dacf..568d9f9a5 100644 --- a/app/scripts/lib/idStore.js +++ b/app/scripts/lib/idStore.js @@ -7,7 +7,6 @@ const extend = require('xtend') const createId = require('web3-provider-engine/util/random-id') const ethBinToOps = require('eth-bin-to-ops') const autoFaucet = require('./auto-faucet') -const configManager = require('./config-manager-singleton') const messageManager = require('./message-manager') const DEFAULT_RPC = 'https://testrpc.metamask.io/' const IdManagement = require('./id-management') @@ -20,6 +19,7 @@ function IdentityStore (opts = {}) { // we just use the ethStore to auto-add accounts this._ethStore = opts.ethStore + this.configManager = opts.configManager // lightwallet key store this._keyStore = null // lightwallet wrapper @@ -43,7 +43,7 @@ function IdentityStore (opts = {}) { IdentityStore.prototype.createNewVault = function (password, entropy, cb) { delete this._keyStore - configManager.clearWallet() + this.configManager.clearWallet() this._createIdmgmt(password, null, entropy, (err) => { if (err) return cb(err) @@ -51,14 +51,14 @@ IdentityStore.prototype.createNewVault = function (password, entropy, cb) { this._didUpdate() this._autoFaucet() - configManager.setShowSeedWords(true) + this.configManager.setShowSeedWords(true) var seedWords = this._idmgmt.getSeed() cb(null, seedWords) }) } IdentityStore.prototype.recoverSeed = function (cb) { - configManager.setShowSeedWords(true) + this.configManager.setShowSeedWords(true) if (!this._idmgmt) return cb(new Error('Unauthenticated. Please sign in.')) var seedWords = this._idmgmt.getSeed() cb(null, seedWords) @@ -79,11 +79,13 @@ IdentityStore.prototype.setStore = function (store) { } IdentityStore.prototype.clearSeedWordCache = function (cb) { + const configManager = this.configManager configManager.setShowSeedWords(false) cb(null, configManager.getSelectedAccount()) } IdentityStore.prototype.getState = function () { + const configManager = this.configManager var seedWords = this.getSeedIfUnlocked() return clone(extend(this._currentState, { isInitialized: !!configManager.getWallet() && !seedWords, @@ -99,6 +101,7 @@ IdentityStore.prototype.getState = function () { } IdentityStore.prototype.getSeedIfUnlocked = function () { + const configManager = this.configManager var showSeed = configManager.getShouldShowSeedWords() var idmgmt = this._idmgmt var shouldShow = showSeed && !!idmgmt @@ -107,10 +110,12 @@ IdentityStore.prototype.getSeedIfUnlocked = function () { } IdentityStore.prototype.getSelectedAddress = function () { + const configManager = this.configManager return configManager.getSelectedAccount() } IdentityStore.prototype.setSelectedAddress = function (address, cb) { + const configManager = this.configManager if (!address) { var addresses = this._getAddresses() address = addresses[0] @@ -123,6 +128,7 @@ IdentityStore.prototype.setSelectedAddress = function (address, cb) { IdentityStore.prototype.revealAccount = function (cb) { const derivedKey = this._idmgmt.derivedKey const keyStore = this._keyStore + const configManager = this.configManager keyStore.setDefaultHdDerivationPath(this.hdPathString) keyStore.generateNewAddress(derivedKey, 1) @@ -158,6 +164,7 @@ IdentityStore.prototype.setLocked = function (cb) { } IdentityStore.prototype.submitPassword = function (password, cb) { + const configManager = this.configManager this.tryPassword(password, (err) => { if (err) return cb(err) // load identities before returning... @@ -177,6 +184,7 @@ IdentityStore.prototype.exportAccount = function (address, cb) { // comes from dapp via zero-client hooked-wallet provider IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDoneCb, cb) { + const configManager = this.configManager var self = this // create txData obj with parameters and meta data var time = (new Date()).getTime() @@ -227,6 +235,7 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone // comes from metamask ui IdentityStore.prototype.approveTransaction = function (txId, cb) { + const configManager = this.configManager var approvalCb = this._unconfTxCbs[txId] || noop // accept tx @@ -240,6 +249,7 @@ IdentityStore.prototype.approveTransaction = function (txId, cb) { // comes from metamask ui IdentityStore.prototype.cancelTransaction = function (txId) { + const configManager = this.configManager var approvalCb = this._unconfTxCbs[txId] || noop // reject tx @@ -347,6 +357,7 @@ IdentityStore.prototype._isUnlocked = function () { // load identities from keyStoreet IdentityStore.prototype._loadIdentities = function () { + const configManager = this.configManager if (!this._isUnlocked()) throw new Error('not unlocked') var addresses = this._getAddresses() @@ -367,6 +378,7 @@ IdentityStore.prototype._loadIdentities = function () { } IdentityStore.prototype.saveAccountLabel = function (account, label, cb) { + const configManager = this.configManager configManager.setNicknameForWallet(account, label) this._loadIdentities() cb(null, label) @@ -379,6 +391,7 @@ IdentityStore.prototype.saveAccountLabel = function (account, label, cb) { // If there is no balance and it mayBeFauceting, // then it is in fact fauceting. IdentityStore.prototype._mayBeFauceting = function (i) { + const configManager = this.configManager var config = configManager.getProvider() if (i === 0 && config.type === 'rpc' && @@ -397,6 +410,7 @@ IdentityStore.prototype.tryPassword = function (password, cb) { } IdentityStore.prototype._createIdmgmt = function (password, seed, entropy, cb) { + const configManager = this.configManager var keyStore = null LightwalletKeyStore.deriveKeyFromPassword(password, (err, derivedKey) => { if (err) return cb(err) @@ -425,6 +439,7 @@ IdentityStore.prototype._createIdmgmt = function (password, seed, entropy, cb) { keyStore: keyStore, derivedKey: derivedKey, hdPathSTring: this.hdPathString, + this.configManager, }) cb() @@ -432,6 +447,7 @@ IdentityStore.prototype._createIdmgmt = function (password, seed, entropy, cb) { } IdentityStore.prototype._restoreFromSeed = function (password, seed, derivedKey) { + const configManager = this.configManager var keyStore = new LightwalletKeyStore(seed, derivedKey, this.hdPathString) keyStore.addHdDerivationPath(this.hdPathString, derivedKey, {curve: 'secp256k1', purpose: 'sign'}) keyStore.setDefaultHdDerivationPath(this.hdPathString) @@ -443,6 +459,7 @@ IdentityStore.prototype._restoreFromSeed = function (password, seed, derivedKey) } IdentityStore.prototype._createFirstWallet = function (entropy, derivedKey) { + const configManager = this.configManager var secretSeed = LightwalletKeyStore.generateRandomSeed(entropy) var keyStore = new LightwalletKeyStore(secretSeed, derivedKey, this.hdPathString) keyStore.addHdDerivationPath(this.hdPathString, derivedKey, {curve: 'secp256k1', purpose: 'sign'}) -- cgit v1.2.3