1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-26 12:29:06 +01:00

Revert "NetworkController refactor for new EthClient interface"

This commit is contained in:
kumavis 2017-10-18 15:09:32 -07:00 committed by GitHub
parent 5eeb144046
commit 8da0d0b28a
11 changed files with 94 additions and 103 deletions

View File

@ -1,12 +1,11 @@
const assert = require('assert') const assert = require('assert')
const EventEmitter = require('events') const EventEmitter = require('events')
const createMetamaskProvider = require('web3-provider-engine/zero.js')
const ObservableStore = require('obs-store') const ObservableStore = require('obs-store')
const ComposedStore = require('obs-store/lib/composed') const ComposedStore = require('obs-store/lib/composed')
const extend = require('xtend') const extend = require('xtend')
const EthQuery = require('eth-query') const EthQuery = require('eth-query')
const createEthRpcClient = require('eth-rpc-client')
const createEventEmitterProxy = require('../lib/events-proxy.js') const createEventEmitterProxy = require('../lib/events-proxy.js')
const createObjectProxy = require('../lib/obj-proxy.js')
const RPC_ADDRESS_LIST = require('../config.js').network const RPC_ADDRESS_LIST = require('../config.js').network
const DEFAULT_RPC = RPC_ADDRESS_LIST['rinkeby'] const DEFAULT_RPC = RPC_ADDRESS_LIST['rinkeby']
@ -18,8 +17,7 @@ module.exports = class NetworkController extends EventEmitter {
this.networkStore = new ObservableStore('loading') this.networkStore = new ObservableStore('loading')
this.providerStore = new ObservableStore(config.provider) this.providerStore = new ObservableStore(config.provider)
this.store = new ComposedStore({ provider: this.providerStore, network: this.networkStore }) this.store = new ComposedStore({ provider: this.providerStore, network: this.networkStore })
this.providerProxy = createObjectProxy() this._proxy = createEventEmitterProxy()
this.blockTrackerProxy = createEventEmitterProxy()
this.on('networkDidChange', this.lookupNetwork) this.on('networkDidChange', this.lookupNetwork)
} }
@ -27,11 +25,12 @@ module.exports = class NetworkController extends EventEmitter {
initializeProvider (_providerParams) { initializeProvider (_providerParams) {
this._baseProviderParams = _providerParams this._baseProviderParams = _providerParams
const rpcUrl = this.getCurrentRpcAddress() const rpcUrl = this.getCurrentRpcAddress()
this._configureStandardClient({ rpcUrl }) this._configureStandardProvider({ rpcUrl })
this.blockTrackerProxy.on('block', this._logBlock.bind(this)) this._proxy.on('block', this._logBlock.bind(this))
this.blockTrackerProxy.on('error', this.verifyNetwork.bind(this)) this._proxy.on('error', this.verifyNetwork.bind(this))
this.ethQuery = new EthQuery(this.providerProxy) this.ethQuery = new EthQuery(this._proxy)
this.lookupNetwork() this.lookupNetwork()
return this._proxy
} }
verifyNetwork () { verifyNetwork () {
@ -77,10 +76,8 @@ module.exports = class NetworkController extends EventEmitter {
assert(type !== 'rpc', `NetworkController.setProviderType - cannot connect by type "rpc"`) assert(type !== 'rpc', `NetworkController.setProviderType - cannot connect by type "rpc"`)
// skip if type already matches // skip if type already matches
if (type === this.getProviderConfig().type) return if (type === this.getProviderConfig().type) return
// lookup rpcTarget for typecreateMetamaskProvider
const rpcTarget = this.getRpcAddressForType(type) const rpcTarget = this.getRpcAddressForType(type)
assert(rpcTarget, `NetworkController - unknown rpc address for type "${type}"`) assert(rpcTarget, `NetworkController - unknown rpc address for type "${type}"`)
// update connectioncreateMetamaskProvider
this.providerStore.updateState({ type, rpcTarget }) this.providerStore.updateState({ type, rpcTarget })
this._switchNetwork({ rpcUrl: rpcTarget }) this._switchNetwork({ rpcUrl: rpcTarget })
} }
@ -100,29 +97,32 @@ module.exports = class NetworkController extends EventEmitter {
_switchNetwork (providerParams) { _switchNetwork (providerParams) {
this.setNetworkState('loading') this.setNetworkState('loading')
this._configureStandardClient(providerParams) this._configureStandardProvider(providerParams)
this.emit('networkDidChange') this.emit('networkDidChange')
} }
_configureStandardClient(_providerParams) { _configureStandardProvider(_providerParams) {
const providerParams = extend(this._baseProviderParams, _providerParams) const providerParams = extend(this._baseProviderParams, _providerParams)
const client = createEthRpcClient(providerParams) const provider = createMetamaskProvider(providerParams)
this._setClient(client) this._setProvider(provider)
} }
_setClient (newClient) { _setProvider (provider) {
// teardown old client // collect old block tracker events
const oldClient = this._currentClient const oldProvider = this._provider
if (oldClient) { let blockTrackerHandlers
oldClient.blockTracker.stop() if (oldProvider) {
// asyncEventEmitter lacks a "removeAllListeners" method // capture old block handlers
// oldClient.blockTracker.removeAllListeners blockTrackerHandlers = oldProvider._blockTracker.proxyEventHandlers
oldClient.blockTracker._events = {} // tear down
oldProvider.removeAllListeners()
oldProvider.stop()
} }
// override block tracler
provider._blockTracker = createEventEmitterProxy(provider._blockTracker, blockTrackerHandlers)
// set as new provider // set as new provider
this._currentClient = newClient this._provider = provider
this.providerProxy.setTarget(newClient.provider) this._proxy.setTarget(provider)
this.blockTrackerProxy.setTarget(newClient.blockTracker)
} }
_logBlock (block) { _logBlock (block) {

View File

@ -46,7 +46,6 @@ module.exports = class TransactionController extends EventEmitter {
this.txStateManager.on('tx:status-update', this.emit.bind(this, 'tx:status-update')) this.txStateManager.on('tx:status-update', this.emit.bind(this, 'tx:status-update'))
this.nonceTracker = new NonceTracker({ this.nonceTracker = new NonceTracker({
provider: this.provider, provider: this.provider,
blockTracker: this.blockTracker,
getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager), getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager),
getConfirmedTransactions: (address) => { getConfirmedTransactions: (address) => {
return this.txStateManager.getFilteredTxList({ return this.txStateManager.getFilteredTxList({

View File

@ -1,5 +1,6 @@
module.exports = function createEventEmitterProxy(eventEmitter, eventHandlers = {}) { module.exports = function createEventEmitterProxy(eventEmitter, listeners) {
let target = eventEmitter let target = eventEmitter
const eventHandlers = listeners || {}
const proxy = new Proxy({}, { const proxy = new Proxy({}, {
get: (obj, name) => { get: (obj, name) => {
// intercept listeners // intercept listeners
@ -13,12 +14,9 @@ module.exports = function createEventEmitterProxy(eventEmitter, eventHandlers =
return true return true
}, },
}) })
proxy.setTarget(eventEmitter)
return proxy
function setTarget (eventEmitter) { function setTarget (eventEmitter) {
target = eventEmitter target = eventEmitter
// migrate eventHandlers // migrate listeners
Object.keys(eventHandlers).forEach((name) => { Object.keys(eventHandlers).forEach((name) => {
eventHandlers[name].forEach((handler) => target.on(name, handler)) eventHandlers[name].forEach((handler) => target.on(name, handler))
}) })
@ -28,4 +26,6 @@ module.exports = function createEventEmitterProxy(eventEmitter, eventHandlers =
eventHandlers[name].push(handler) eventHandlers[name].push(handler)
target.on(name, handler) target.on(name, handler)
} }
if (listeners) proxy.setTarget(eventEmitter)
return proxy
} }

View File

@ -4,9 +4,8 @@ const Mutex = require('await-semaphore').Mutex
class NonceTracker { class NonceTracker {
constructor ({ provider, blockTracker, getPendingTransactions, getConfirmedTransactions }) { constructor ({ provider, getPendingTransactions, getConfirmedTransactions }) {
this.provider = provider this.provider = provider
this.blockTracker = blockTracker
this.ethQuery = new EthQuery(provider) this.ethQuery = new EthQuery(provider)
this.getPendingTransactions = getPendingTransactions this.getPendingTransactions = getPendingTransactions
this.getConfirmedTransactions = getConfirmedTransactions this.getConfirmedTransactions = getConfirmedTransactions
@ -54,7 +53,7 @@ class NonceTracker {
} }
async _getCurrentBlock () { async _getCurrentBlock () {
const blockTracker = this.blockTracker const blockTracker = this._getBlockTracker()
const currentBlock = blockTracker.getCurrentBlock() const currentBlock = blockTracker.getCurrentBlock()
if (currentBlock) return currentBlock if (currentBlock) return currentBlock
return await Promise((reject, resolve) => { return await Promise((reject, resolve) => {
@ -140,6 +139,11 @@ class NonceTracker {
return { name: 'local', nonce: highest, details: { startPoint, highest } } return { name: 'local', nonce: highest, details: { startPoint, highest } }
} }
// this is a hotfix for the fact that the blockTracker will
// change when the network changes
_getBlockTracker () {
return this.provider._blockTracker
}
} }
module.exports = NonceTracker module.exports = NonceTracker

View File

@ -1,19 +0,0 @@
module.exports = function createObjectProxy(obj) {
let target = obj
const proxy = new Proxy({}, {
get: (obj, name) => {
// intercept setTarget
if (name === 'setTarget') return setTarget
return target[name]
},
set: (obj, name, value) => {
target[name] = value
return true
},
})
return proxy
function setTarget (obj) {
target = obj
}
}

View File

@ -81,24 +81,9 @@ module.exports = class MetamaskController extends EventEmitter {
}) })
this.blacklistController.scheduleUpdates() this.blacklistController.scheduleUpdates()
// rpc provider and block tracker // rpc provider
this.networkController.initializeProvider({ this.provider = this.initializeProvider()
scaffold: { this.blockTracker = this.provider._blockTracker
eth_syncing: false,
web3_clientVersion: `MetaMask/v${version}`,
},
// account mgmt
getAccounts: nodeify(this.getAccounts, this),
// tx signing
processTransaction: nodeify(this.newTransaction, this),
// old style msg signing
processMessage: this.newUnsignedMessage.bind(this),
// personal_sign msg signing
processPersonalMessage: this.newUnsignedPersonalMessage.bind(this),
processTypedMessage: this.newUnsignedTypedMessage.bind(this),
})
this.provider = this.networkController.providerProxy
this.blockTracker = this.networkController.blockTrackerProxy
// eth data query tools // eth data query tools
this.ethQuery = new EthQuery(this.provider) this.ethQuery = new EthQuery(this.provider)
@ -233,6 +218,36 @@ module.exports = class MetamaskController extends EventEmitter {
// Constructor helpers // Constructor helpers
// //
initializeProvider () {
const providerOpts = {
static: {
eth_syncing: false,
web3_clientVersion: `MetaMask/v${version}`,
},
// account mgmt
getAccounts: (cb) => {
const isUnlocked = this.keyringController.memStore.getState().isUnlocked
const result = []
const selectedAddress = this.preferencesController.getSelectedAddress()
// only show address if account is unlocked
if (isUnlocked && selectedAddress) {
result.push(selectedAddress)
}
cb(null, result)
},
// tx signing
processTransaction: nodeify(async (txParams) => await this.txController.newUnapprovedTransaction(txParams), this),
// old style msg signing
processMessage: this.newUnsignedMessage.bind(this),
// personal_sign msg signing
processPersonalMessage: this.newUnsignedPersonalMessage.bind(this),
processTypedMessage: this.newUnsignedTypedMessage.bind(this),
}
const providerProxy = this.networkController.initializeProvider(providerOpts)
return providerProxy
}
initPublicConfigStore () { initPublicConfigStore () {
// get init state // get init state
const publicConfigStore = new ObservableStore() const publicConfigStore = new ObservableStore()
@ -468,18 +483,6 @@ module.exports = class MetamaskController extends EventEmitter {
// Opinionated Keyring Management // Opinionated Keyring Management
// //
async getAccounts () {
const isUnlocked = this.keyringController.memStore.getState().isUnlocked
const result = []
const selectedAddress = this.preferencesController.getSelectedAddress()
// only show address if account is unlocked
if (isUnlocked && selectedAddress) {
result.push(selectedAddress)
}
return result
}
addNewAccount (cb) { addNewAccount (cb) {
const primaryKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0] const primaryKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0]
if (!primaryKeyring) return cb(new Error('MetamaskController - No HD Key Tree found')) if (!primaryKeyring) return cb(new Error('MetamaskController - No HD Key Tree found'))
@ -526,11 +529,6 @@ module.exports = class MetamaskController extends EventEmitter {
// Identity Management // Identity Management
// //
// this function wrappper lets us pass the fn reference before txController is instantiated
async newTransaction (txParams) {
return await this.txController.newUnapprovedTransaction(txParams)
}
newUnsignedMessage (msgParams, cb) { newUnsignedMessage (msgParams, cb) {
const msgId = this.messageManager.addUnapprovedMessage(msgParams) const msgId = this.messageManager.addUnapprovedMessage(msgParams)
this.sendUpdate() this.sendUpdate()

View File

@ -71,11 +71,9 @@
"eth-contract-metadata": "^1.1.4", "eth-contract-metadata": "^1.1.4",
"eth-hd-keyring": "^1.2.1", "eth-hd-keyring": "^1.2.1",
"eth-json-rpc-filters": "^1.2.2", "eth-json-rpc-filters": "^1.2.2",
"eth-json-rpc-middleware": "^1.4.3",
"eth-keyring-controller": "^2.1.0", "eth-keyring-controller": "^2.1.0",
"eth-phishing-detect": "^1.1.4", "eth-phishing-detect": "^1.1.4",
"eth-query": "^2.1.2", "eth-query": "^2.1.2",
"eth-rpc-client": "^1.1.3",
"eth-sig-util": "^1.4.0", "eth-sig-util": "^1.4.0",
"eth-simple-keyring": "^1.2.0", "eth-simple-keyring": "^1.2.0",
"eth-token-tracker": "^1.1.4", "eth-token-tracker": "^1.1.4",

View File

@ -3,9 +3,6 @@ const PASSWORD = 'password123'
QUnit.module('first time usage') QUnit.module('first time usage')
QUnit.test('render init screen', (assert) => { QUnit.test('render init screen', (assert) => {
// intercept reload attempts
window.onbeforeunload = () => true
const done = assert.async() const done = assert.async()
runFirstTimeUsageTest(assert).then(done).catch((err) => { runFirstTimeUsageTest(assert).then(done).catch((err) => {
assert.notOk(err, `Error was thrown: ${err.stack}`) assert.notOk(err, `Error was thrown: ${err.stack}`)

View File

@ -14,15 +14,15 @@ describe('# Network Controller', function () {
}, },
}) })
networkController.initializeProvider(networkControllerProviderInit) networkController.initializeProvider(networkControllerProviderInit, dummyProviderConstructor)
}) })
describe('network', function () { describe('network', function () {
describe('#provider', function () { describe('#provider', function () {
it('provider should be updatable without reassignment', function () { it('provider should be updatable without reassignment', function () {
networkController.initializeProvider(networkControllerProviderInit) networkController.initializeProvider(networkControllerProviderInit, dummyProviderConstructor)
const providerProxy = networkController.providerProxy const proxy = networkController._proxy
providerProxy.setTarget({ test: true }) proxy.setTarget({ test: true, on: () => {} })
assert.ok(providerProxy.test) assert.ok(proxy.test)
}) })
}) })
describe('#getNetworkState', function () { describe('#getNetworkState', function () {
@ -66,4 +66,19 @@ describe('# Network Controller', function () {
}) })
}) })
function dummyProviderConstructor() {
return {
// provider
sendAsync: noop,
// block tracker
_blockTracker: {},
start: noop,
stop: noop,
on: noop,
addListener: noop,
once: noop,
removeAllListeners: noop,
}
}
function noop() {} function noop() {}

View File

@ -190,13 +190,12 @@ function generateNonceTrackerWith (pending, confirmed, providerStub = '0x0') {
providerResultStub.result = providerStub providerResultStub.result = providerStub
const provider = { const provider = {
sendAsync: (_, cb) => { cb(undefined, providerResultStub) }, sendAsync: (_, cb) => { cb(undefined, providerResultStub) },
} _blockTracker: {
const blockTracker = { getCurrentBlock: () => '0x11b568',
getCurrentBlock: () => '0x11b568', },
} }
return new NonceTracker({ return new NonceTracker({
provider, provider,
blockTracker,
getPendingTransactions, getPendingTransactions,
getConfirmedTransactions, getConfirmedTransactions,
}) })

View File

@ -319,7 +319,7 @@ App.prototype.renderNetworkDropdown = function () {
[ [
h('i.fa.fa-question-circle.fa-lg.menu-icon'), h('i.fa.fa-question-circle.fa-lg.menu-icon'),
'Localhost 8545', 'Localhost 8545',
providerType === 'localhost' ? h('.check', '✓') : null, activeNetwork === 'http://localhost:8545' ? h('.check', '✓') : null,
] ]
), ),