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:
parent
5eeb144046
commit
8da0d0b28a
@ -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) {
|
||||||
|
@ -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({
|
||||||
|
@ -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
|
||||||
}
|
}
|
@ -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
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
@ -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()
|
||||||
|
@ -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",
|
||||||
|
@ -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}`)
|
||||||
|
@ -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() {}
|
@ -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,
|
||||||
})
|
})
|
||||||
|
@ -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,
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user