mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
network - create provider and block-tracker via json-rpc-engine
This commit is contained in:
parent
708422432c
commit
088d7930e0
34
app/scripts/controllers/network/createInfuraClient.js
Normal file
34
app/scripts/controllers/network/createInfuraClient.js
Normal file
@ -0,0 +1,34 @@
|
||||
const mergeMiddleware = require('json-rpc-engine/src/mergeMiddleware')
|
||||
const createAsyncMiddleware = require('json-rpc-engine/src/createAsyncMiddleware')
|
||||
const createBlockRefMiddleware = require('eth-json-rpc-middleware/block-ref')
|
||||
const createBlockRefMiddleware = require('eth-json-rpc-middleware/block-cache')
|
||||
const BlockTracker = require('eth-block-tracker')
|
||||
|
||||
module.exports = createInfuraClient
|
||||
|
||||
function createInfuraClient({ network }) {
|
||||
const infuraMiddleware = createInfuraMiddleware({ network })
|
||||
const blockProvider = providerFromMiddleware(infuraMiddleware)
|
||||
const blockTracker = new BlockTracker({ provider: blockProvider })
|
||||
|
||||
const networkMiddleware = mergeMiddleware([
|
||||
createBlockRefMiddleware({ blockTracker }),
|
||||
createBlockCacheMiddleware({ blockTracker }),
|
||||
createInflightMiddleware(),
|
||||
createBlockTrackerInspectorMiddleware({ blockTracker }),
|
||||
infuraMiddleware,
|
||||
])
|
||||
return { networkMiddleware, blockTracker }
|
||||
}
|
||||
|
||||
// inspect if response contains a block ref higher than our latest block
|
||||
const futureBlockRefRequests = ['eth_getTransactionByHash', 'eth_getTransactionReceipt']
|
||||
function createBlockTrackerInspectorMiddleware ({ blockTracker }) {
|
||||
return createAsyncMiddleware(async (req, res, next) => {
|
||||
if (!futureBlockRefRequests.includes(req.method)) return next()
|
||||
await next()
|
||||
const blockNumber = Number.parseInt(res.result.blockNumber, 16)
|
||||
const currentBlockNumber = Number.parseInt(blockTracker.getCurrentBlock(), 16)
|
||||
if (blockNumber > currentBlockNumber) await blockTracker.checkForLatestBlock()
|
||||
})
|
||||
}
|
35
app/scripts/controllers/network/createJsonRpcClient.js
Normal file
35
app/scripts/controllers/network/createJsonRpcClient.js
Normal file
@ -0,0 +1,35 @@
|
||||
const mergeMiddleware = require('json-rpc-engine/src/mergeMiddleware')
|
||||
const createAsyncMiddleware = require('json-rpc-engine/src/createAsyncMiddleware')
|
||||
const createFetchMiddleware = require('eth-json-rpc-middleware/fetch')
|
||||
const createBlockRefMiddleware = require('eth-json-rpc-middleware/block-ref')
|
||||
const createBlockRefMiddleware = require('eth-json-rpc-middleware/block-cache')
|
||||
const BlockTracker = require('eth-block-tracker')
|
||||
|
||||
module.exports = createJsonRpcClient
|
||||
|
||||
function createJsonRpcClient({ rpcUrl }) {
|
||||
const fetchMiddleware = createFetchMiddleware({ rpcUrl })
|
||||
const blockProvider = providerFromMiddleware(fetchMiddleware)
|
||||
const blockTracker = new BlockTracker({ provider: blockProvider })
|
||||
|
||||
const networkMiddleware = mergeMiddleware([
|
||||
createBlockRefMiddleware({ blockTracker }),
|
||||
createBlockCacheMiddleware({ blockTracker }),
|
||||
createInflightMiddleware(),
|
||||
createBlockTrackerInspectorMiddleware({ blockTracker }),
|
||||
fetchMiddleware,
|
||||
])
|
||||
return { networkMiddleware, blockTracker }
|
||||
}
|
||||
|
||||
// inspect if response contains a block ref higher than our latest block
|
||||
const futureBlockRefRequests = ['eth_getTransactionByHash', 'eth_getTransactionReceipt']
|
||||
function createBlockTrackerInspectorMiddleware ({ blockTracker }) {
|
||||
return createAsyncMiddleware(async (req, res, next) => {
|
||||
if (!futureBlockRefRequests.includes(req.method)) return next()
|
||||
await next()
|
||||
const blockNumber = Number.parseInt(res.result.blockNumber, 16)
|
||||
const currentBlockNumber = Number.parseInt(blockTracker.getCurrentBlock(), 16)
|
||||
if (blockNumber > currentBlockNumber) await blockTracker.checkForLatestBlock()
|
||||
})
|
||||
}
|
33
app/scripts/controllers/network/createLocalhostClient.js
Normal file
33
app/scripts/controllers/network/createLocalhostClient.js
Normal file
@ -0,0 +1,33 @@
|
||||
const mergeMiddleware = require('json-rpc-engine/src/mergeMiddleware')
|
||||
const createAsyncMiddleware = require('json-rpc-engine/src/createAsyncMiddleware')
|
||||
const createFetchMiddleware = require('eth-json-rpc-middleware/fetch')
|
||||
const createBlockRefMiddleware = require('eth-json-rpc-middleware/block-ref')
|
||||
const createBlockRefMiddleware = require('eth-json-rpc-middleware/block-cache')
|
||||
const BlockTracker = require('eth-block-tracker')
|
||||
|
||||
module.exports = createLocalhostClient
|
||||
|
||||
function createLocalhostClient() {
|
||||
const fetchMiddleware = createFetchMiddleware({ rpcUrl: 'http://localhost:8545/' })
|
||||
const blockProvider = providerFromMiddleware(fetchMiddleware)
|
||||
const blockTracker = new BlockTracker({ provider: blockProvider, pollingInterval: 1000 })
|
||||
|
||||
const networkMiddleware = mergeMiddleware([
|
||||
createBlockRefMiddleware({ blockTracker }),
|
||||
createBlockTrackerInspectorMiddleware({ blockTracker }),
|
||||
fetchMiddleware,
|
||||
])
|
||||
return { networkMiddleware, blockTracker }
|
||||
}
|
||||
|
||||
// inspect if response contains a block ref higher than our latest block
|
||||
const futureBlockRefRequests = ['eth_getTransactionByHash', 'eth_getTransactionReceipt']
|
||||
function createBlockTrackerInspectorMiddleware ({ blockTracker }) {
|
||||
return createAsyncMiddleware(async (req, res, next) => {
|
||||
if (!futureBlockRefRequests.includes(req.method)) return next()
|
||||
await next()
|
||||
const blockNumber = Number.parseInt(res.result.blockNumber, 16)
|
||||
const currentBlockNumber = Number.parseInt(blockTracker.getCurrentBlock(), 16)
|
||||
if (blockNumber > currentBlockNumber) await blockTracker.checkForLatestBlock()
|
||||
})
|
||||
}
|
43
app/scripts/controllers/network/createMetamaskMiddleware.js
Normal file
43
app/scripts/controllers/network/createMetamaskMiddleware.js
Normal file
@ -0,0 +1,43 @@
|
||||
const mergeMiddleware = require('json-rpc-engine/src/mergeMiddleware')
|
||||
const createScaffoldMiddleware = require('json-rpc-engine/src/scaffold')
|
||||
const createAsyncMiddleware = require('json-rpc-engine/src/createAsyncMiddleware')
|
||||
const createWalletSubprovider = require('eth-json-rpc-middleware/wallet')
|
||||
|
||||
module.exports = createMetamaskMiddleware
|
||||
|
||||
function createMetamaskMiddleware({
|
||||
version,
|
||||
getAccounts,
|
||||
processTransaction,
|
||||
processEthSignMessage,
|
||||
processTypedMessage,
|
||||
processPersonalMessage,
|
||||
getPendingNonce
|
||||
}) {
|
||||
const metamaskMiddleware = mergeMiddleware([
|
||||
createScaffoldMiddleware({
|
||||
// staticSubprovider
|
||||
eth_syncing: false,
|
||||
web3_clientVersion: `MetaMask/v${version}`,
|
||||
}),
|
||||
createWalletSubprovider({
|
||||
getAccounts,
|
||||
processTransaction,
|
||||
processEthSignMessage,
|
||||
processTypedMessage,
|
||||
processPersonalMessage,
|
||||
}),
|
||||
createPendingNonceMiddleware({ getPendingNonce }),
|
||||
})
|
||||
return metamaskMiddleware
|
||||
}
|
||||
|
||||
function createPendingNonceMiddleware ({ getPendingNonce }) {
|
||||
return createAsyncMiddleware(async (req, res, next) => {
|
||||
if (req.method !== 'eth_getTransactionCount') return next()
|
||||
const address = req.params[0]
|
||||
const blockRef = req.params[1]
|
||||
if (blockRef !== 'pending') return next()
|
||||
req.result = await getPendingNonce(address)
|
||||
})
|
||||
}
|
@ -1,14 +1,17 @@
|
||||
const assert = require('assert')
|
||||
const EventEmitter = require('events')
|
||||
const createMetamaskProvider = require('web3-provider-engine/zero.js')
|
||||
const SubproviderFromProvider = require('web3-provider-engine/subproviders/provider.js')
|
||||
const createInfuraProvider = require('eth-json-rpc-infura/src/createProvider')
|
||||
const ObservableStore = require('obs-store')
|
||||
const ComposedStore = require('obs-store/lib/composed')
|
||||
const extend = require('xtend')
|
||||
const EthQuery = require('eth-query')
|
||||
const createEventEmitterProxy = require('../../lib/events-proxy.js')
|
||||
const log = require('loglevel')
|
||||
const createMetamaskMiddleware = require('./createMetamaskMiddleware')
|
||||
const createInfuraClient = require('./createInfuraClient')
|
||||
const createJsonRpcClient = require('./createJsonRpcClient')
|
||||
const createLocalhostClient = require('./createLocalhostClient')
|
||||
// const createEventEmitterProxy = require('../../lib/events-proxy.js')
|
||||
const { createSwappableProxy, createEventEmitterProxy } = require('swappable-obj-proxy')
|
||||
|
||||
const {
|
||||
ROPSTEN,
|
||||
RINKEBY,
|
||||
@ -38,21 +41,27 @@ module.exports = class NetworkController extends EventEmitter {
|
||||
this.providerStore = new ObservableStore(providerConfig)
|
||||
this.networkStore = new ObservableStore('loading')
|
||||
this.store = new ComposedStore({ provider: this.providerStore, network: this.networkStore })
|
||||
// create event emitter proxy
|
||||
this._proxy = createEventEmitterProxy()
|
||||
|
||||
this.on('networkDidChange', this.lookupNetwork)
|
||||
// provider and block tracker
|
||||
this._provider = null
|
||||
this._blockTracker = null
|
||||
// provider and block tracker proxies - because the network changes
|
||||
this._providerProxy = null
|
||||
this._blockTrackerProxy = null
|
||||
}
|
||||
|
||||
initializeProvider (_providerParams) {
|
||||
this._baseProviderParams = _providerParams
|
||||
initializeProvider (providerParams) {
|
||||
this._baseProviderParams = providerParams
|
||||
const { type, rpcTarget } = this.providerStore.getState()
|
||||
this._configureProvider({ type, rpcTarget })
|
||||
this._proxy.on('block', this._logBlock.bind(this))
|
||||
this._proxy.on('error', this.verifyNetwork.bind(this))
|
||||
this.ethQuery = new EthQuery(this._proxy)
|
||||
this.lookupNetwork()
|
||||
return this._proxy
|
||||
}
|
||||
|
||||
// return the proxies so the references will always be good
|
||||
getProviderAndBlockTracker() {
|
||||
const provider = this._providerProxy
|
||||
const blockTracker = this._blockTracker
|
||||
return { provider, blockTracker }
|
||||
}
|
||||
|
||||
verifyNetwork () {
|
||||
@ -74,10 +83,11 @@ module.exports = class NetworkController extends EventEmitter {
|
||||
|
||||
lookupNetwork () {
|
||||
// Prevent firing when provider is not defined.
|
||||
if (!this.ethQuery || !this.ethQuery.sendAsync) {
|
||||
return log.warn('NetworkController - lookupNetwork aborted due to missing ethQuery')
|
||||
if (!this._provider) {
|
||||
return log.warn('NetworkController - lookupNetwork aborted due to missing provider')
|
||||
}
|
||||
this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => {
|
||||
const ethQuery = new EthQuery(this._provider)
|
||||
ethQuery.sendAsync({ method: 'net_version' }, (err, network) => {
|
||||
if (err) return this.setNetworkState('loading')
|
||||
log.info('web3.getNetwork returned ' + network)
|
||||
this.setNetworkState(network)
|
||||
@ -123,7 +133,7 @@ module.exports = class NetworkController extends EventEmitter {
|
||||
this._configureInfuraProvider(opts)
|
||||
// other type-based rpc endpoints
|
||||
} else if (type === LOCALHOST) {
|
||||
this._configureStandardProvider({ rpcUrl: LOCALHOST_RPC_URL })
|
||||
this._configureLocalhostProvider()
|
||||
// url-based rpc endpoints
|
||||
} else if (type === 'rpc'){
|
||||
this._configureStandardProvider({ rpcUrl: rpcTarget })
|
||||
@ -133,47 +143,47 @@ module.exports = class NetworkController extends EventEmitter {
|
||||
}
|
||||
|
||||
_configureInfuraProvider ({ type }) {
|
||||
log.info('_configureInfuraProvider', type)
|
||||
const infuraProvider = createInfuraProvider({ network: type })
|
||||
const infuraSubprovider = new SubproviderFromProvider(infuraProvider)
|
||||
const providerParams = extend(this._baseProviderParams, {
|
||||
engineParams: {
|
||||
pollingInterval: 8000,
|
||||
blockTrackerProvider: infuraProvider,
|
||||
},
|
||||
dataSubprovider: infuraSubprovider,
|
||||
})
|
||||
const provider = createMetamaskProvider(providerParams)
|
||||
this._setProvider(provider)
|
||||
log.info('NetworkController - configureInfuraProvider', type)
|
||||
const networkClient = createInfuraClient({ network: type })
|
||||
this._setNetworkClient(networkClient)
|
||||
}
|
||||
|
||||
_configureLocalhostProvider () {
|
||||
log.info('NetworkController - configureLocalhostProvider')
|
||||
const networkClient = createLocalhostClient()
|
||||
this._setNetworkClient(networkClient)
|
||||
}
|
||||
|
||||
_configureStandardProvider ({ rpcUrl }) {
|
||||
const providerParams = extend(this._baseProviderParams, {
|
||||
rpcUrl,
|
||||
engineParams: {
|
||||
pollingInterval: 8000,
|
||||
},
|
||||
})
|
||||
const provider = createMetamaskProvider(providerParams)
|
||||
this._setProvider(provider)
|
||||
log.info('NetworkController - configureStandardProvider', rpcUrl)
|
||||
const networkClient = createJsonRpcClient({ rpcUrl })
|
||||
this._setNetworkClient(networkClient)
|
||||
}
|
||||
|
||||
_setProvider (provider) {
|
||||
// collect old block tracker events
|
||||
const oldProvider = this._provider
|
||||
let blockTrackerHandlers
|
||||
if (oldProvider) {
|
||||
// capture old block handlers
|
||||
blockTrackerHandlers = oldProvider._blockTracker.proxyEventHandlers
|
||||
// tear down
|
||||
oldProvider.removeAllListeners()
|
||||
oldProvider.stop()
|
||||
_setNetworkClient ({ networkMiddleware, blockTracker }) {
|
||||
const metamaskMiddleware = createMetamaskMiddleware(this._baseProviderParams)
|
||||
const engine = new JsonRpcEngine()
|
||||
engine.push(metamaskMiddleware)
|
||||
engine.push(networkMiddleware)
|
||||
const provider = providerFromEngine(engine)
|
||||
this._setProviderAndBlockTracker({ provider, blockTracker })
|
||||
}
|
||||
|
||||
_setProviderAndBlockTracker ({ provider, blockTracker }) {
|
||||
// update or intialize proxies
|
||||
if (this._providerProxy) {
|
||||
this._providerProxy.setTarget(provider)
|
||||
} else {
|
||||
this._providerProxy = createSwappableProxy(provider)
|
||||
}
|
||||
// override block tracler
|
||||
provider._blockTracker = createEventEmitterProxy(provider._blockTracker, blockTrackerHandlers)
|
||||
// set as new provider
|
||||
if (this._blockTrackerProxy) {
|
||||
this._blockTrackerProxy.setTarget(blockTracker)
|
||||
} else {
|
||||
this._blockTrackerProxy = createEventEmitterProxy(blockTracker)
|
||||
}
|
||||
// set new provider and blockTracker
|
||||
this._provider = provider
|
||||
this._proxy.setTarget(provider)
|
||||
this._blockTracker = blockTracker
|
||||
}
|
||||
|
||||
_logBlock (block) {
|
||||
|
@ -63,6 +63,7 @@ class TransactionController extends EventEmitter {
|
||||
this.store = this.txStateManager.store
|
||||
this.nonceTracker = new NonceTracker({
|
||||
provider: this.provider,
|
||||
blockTracker: this.blockTracker,
|
||||
getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager),
|
||||
getConfirmedTransactions: this.txStateManager.getConfirmedTransactions.bind(this.txStateManager),
|
||||
})
|
||||
|
@ -12,8 +12,9 @@ const Mutex = require('await-semaphore').Mutex
|
||||
*/
|
||||
class NonceTracker {
|
||||
|
||||
constructor ({ provider, getPendingTransactions, getConfirmedTransactions }) {
|
||||
constructor ({ provider, blockTracker, getPendingTransactions, getConfirmedTransactions }) {
|
||||
this.provider = provider
|
||||
this.blockTracker = blockTracker
|
||||
this.ethQuery = new EthQuery(provider)
|
||||
this.getPendingTransactions = getPendingTransactions
|
||||
this.getConfirmedTransactions = getConfirmedTransactions
|
||||
@ -75,11 +76,10 @@ class NonceTracker {
|
||||
}
|
||||
|
||||
async _getCurrentBlock () {
|
||||
const blockTracker = this._getBlockTracker()
|
||||
const currentBlock = blockTracker.getCurrentBlock()
|
||||
const currentBlock = this.blockTracker.getCurrentBlock()
|
||||
if (currentBlock) return currentBlock
|
||||
return await new Promise((reject, resolve) => {
|
||||
blockTracker.once('latest', resolve)
|
||||
this.blockTracker.once('latest', resolve)
|
||||
})
|
||||
}
|
||||
|
||||
@ -171,16 +171,6 @@ class NonceTracker {
|
||||
|
||||
return { name: 'local', nonce: highest, details: { startPoint, highest } }
|
||||
}
|
||||
|
||||
// this is a hotfix for the fact that the blockTracker will
|
||||
// change when the network changes
|
||||
|
||||
/**
|
||||
@returns {Object} the current blockTracker
|
||||
*/
|
||||
_getBlockTracker () {
|
||||
return this.provider._blockTracker
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = NonceTracker
|
||||
|
@ -103,8 +103,9 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
this.blacklistController.scheduleUpdates()
|
||||
|
||||
// rpc provider
|
||||
this.provider = this.initializeProvider()
|
||||
this.blockTracker = this.provider._blockTracker
|
||||
this.initializeProvider()
|
||||
this.provider = this.networkController.getProviderAndBlockTracker().provider
|
||||
this.blockTracker = this.networkController.getProviderAndBlockTracker().blockTracker
|
||||
|
||||
// token exchange rate tracker
|
||||
this.tokenRatesController = new TokenRatesController({
|
||||
@ -1033,7 +1034,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
// create filter polyfill middleware
|
||||
const filterMiddleware = createFilterMiddleware({
|
||||
provider: this.provider,
|
||||
blockTracker: this.provider._blockTracker,
|
||||
blockTracker: this.blockTracker,
|
||||
})
|
||||
|
||||
engine.push(createOriginMiddleware({ origin }))
|
||||
|
@ -91,6 +91,7 @@
|
||||
"ensnare": "^1.0.0",
|
||||
"eslint-plugin-react": "^7.4.0",
|
||||
"eth-bin-to-ops": "^1.0.1",
|
||||
"eth-block-tracker": "github:metamask/eth-block-tracker#acbcfda348c309ece0fb96fad78d4861d08f5a91",
|
||||
"eth-contract-metadata": "^1.1.5",
|
||||
"eth-hd-keyring": "^1.2.1",
|
||||
"eth-json-rpc-filters": "^1.2.6",
|
||||
@ -129,7 +130,7 @@
|
||||
"iframe-stream": "^3.0.0",
|
||||
"inject-css": "^0.1.1",
|
||||
"jazzicon": "^1.2.0",
|
||||
"json-rpc-engine": "^3.6.1",
|
||||
"json-rpc-engine": "^3.7.0",
|
||||
"json-rpc-middleware-stream": "^1.0.1",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"lodash.memoize": "^4.1.2",
|
||||
@ -185,6 +186,7 @@
|
||||
"shallow-copy": "0.0.1",
|
||||
"sw-controller": "^1.0.3",
|
||||
"sw-stream": "^2.0.2",
|
||||
"swappable-obj-proxy": "^1.0.0",
|
||||
"textarea-caret": "^3.0.1",
|
||||
"through2": "^2.0.3",
|
||||
"valid-url": "^1.0.9",
|
||||
|
@ -226,14 +226,14 @@ function generateNonceTrackerWith (pending, confirmed, providerStub = '0x0') {
|
||||
providerResultStub.result = providerStub
|
||||
const provider = {
|
||||
sendAsync: (_, cb) => { cb(undefined, providerResultStub) },
|
||||
_blockTracker: {
|
||||
getCurrentBlock: () => '0x11b568',
|
||||
},
|
||||
}
|
||||
const blockTracker = {
|
||||
getCurrentBlock: () => '0x11b568',
|
||||
}
|
||||
return new NonceTracker({
|
||||
provider,
|
||||
blockTracker,
|
||||
getPendingTransactions,
|
||||
getConfirmedTransactions,
|
||||
})
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user