Skip to content

Commit

Permalink
Merge pull request #308 from poanetwork/fix-gasprice-estimation
Browse files Browse the repository at this point in the history
Fix blocks tracking: reset recent blocks array on network change
  • Loading branch information
vbaranov committed Aug 22, 2019
2 parents 5279197 + 5aad4c9 commit dcf3e6b
Show file tree
Hide file tree
Showing 16 changed files with 419 additions and 181 deletions.
18 changes: 18 additions & 0 deletions app/scripts/controllers/network/createLocalhostClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ const mergeMiddleware = require('json-rpc-engine/src/mergeMiddleware')
const createFetchMiddleware = require('eth-json-rpc-middleware/fetch')
const createBlockRefRewriteMiddleware = require('eth-json-rpc-middleware/block-ref-rewrite')
const createBlockTrackerInspectorMiddleware = require('eth-json-rpc-middleware/block-tracker-inspector')
const createAsyncMiddleware = require('json-rpc-engine/src/createAsyncMiddleware')
const providerFromMiddleware = require('eth-json-rpc-middleware/providerFromMiddleware')
const BlockTracker = require('eth-block-tracker')

const inTest = process.env.IN_TEST === 'true'

module.exports = createLocalhostClient

function createLocalhostClient () {
Expand All @@ -13,9 +16,24 @@ function createLocalhostClient () {
const blockTracker = new BlockTracker({ provider: blockProvider, pollingInterval: 1000 })

const networkMiddleware = mergeMiddleware([
createEstimateGasMiddleware(),
createBlockRefRewriteMiddleware({ blockTracker }),
createBlockTrackerInspectorMiddleware({ blockTracker }),
fetchMiddleware,
])
return { networkMiddleware, blockTracker }
}

function delay (time) {
return new Promise(resolve => setTimeout(resolve, time))
}


function createEstimateGasMiddleware () {
return createAsyncMiddleware(async (req, _, next) => {
if (req.method === 'eth_estimateGas' && inTest) {
await delay(2000)
}
return next()
})
}
4 changes: 2 additions & 2 deletions app/scripts/controllers/network/createPocketClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,15 @@ function getNetworkIds ({ network }) {
ticker = POA_TICK
break
case POA_SOKOL:
netId= POA_SOKOL_CODE.toString()
netId = POA_SOKOL_CODE.toString()
chainId = POA_SOKOL_CHAINID
ticker = POA_TICK
break
default:
throw new Error(`createPocketClient - unknown network "${network}"`)
}
return {
chainId, netId, ticker
chainId, netId, ticker,
}
}

Expand Down
20 changes: 10 additions & 10 deletions app/scripts/controllers/network/enums.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ const RSK = 'rsk'
const RSK_TESTNET = 'rsk_testnet'
const LOCALHOST = 'localhost'

const ETH_TICK = "ETH"
const POA_TICK = "POA"
const ETH_TICK = 'ETH'
const POA_TICK = 'POA'

const MAINNET_CHAINID = "0X01"
const ROPSTEN_CHAINID = "0x03"
const RINKEBY_CHAINID = "0x04"
const KOVAN_CHAINID = "0x2a"
const GOERLI_TESTNET_CHAINID = "0X5"
const POA_CHAINID = "0x63"
const DAI_CHAINID = "0x64"
const POA_SOKOL_CHAINID = "0x4D"
const MAINNET_CHAINID = '0X01'
const ROPSTEN_CHAINID = '0x03'
const RINKEBY_CHAINID = '0x04'
const KOVAN_CHAINID = '0x2a'
const GOERLI_TESTNET_CHAINID = '0X5'
const POA_CHAINID = '0x63'
const DAI_CHAINID = '0x64'
const POA_SOKOL_CHAINID = '0x4D'

const POA_CODE = 99
const DAI_CODE = 100
Expand Down
123 changes: 86 additions & 37 deletions app/scripts/controllers/network/network.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ const createPocketClient = require('./createPocketClient')
const { createSwappableProxy, createEventEmitterProxy } = require('swappable-obj-proxy')
const ethNetProps = require('eth-net-props')
const parse = require('url-parse')
const extend = require('extend')
const networks = { networkList: {} }
const { isKnownProvider } = require('../../../../old-ui/app/util')

const {
ROPSTEN,
Expand Down Expand Up @@ -43,8 +46,21 @@ const env = process.env.METAMASK_ENV
const METAMASK_DEBUG = process.env.METAMASK_DEBUG
const testMode = (METAMASK_DEBUG || env === 'test')

let defaultProviderConfigType
if (process.env.IN_TEST === 'true') {
defaultProviderConfigType = LOCALHOST
} else if (testMode) {
defaultProviderConfigType = POA_SOKOL
} else {
defaultProviderConfigType = POA
}

const defaultProviderConfig = {
type: testMode ? POA_SOKOL : POA,
type: defaultProviderConfigType,
}

const defaultNetworkConfig = {
ticker: 'POA',
}

module.exports = class NetworkController extends EventEmitter {
Expand All @@ -58,6 +74,7 @@ module.exports = class NetworkController extends EventEmitter {
this.providerStore = new ObservableStore(providerConfig)
this.networkStore = new ObservableStore('loading')
this.dProviderStore = new ObservableStore({dProvider: false})
this.networkConfig = new ObservableStore(defaultNetworkConfig)
this.store = new ComposedStore({ provider: this.providerStore, network: this.networkStore, dProviderStore: this.dProviderStore })
this.on('networkDidChange', this.lookupNetwork)
// provider and block tracker
Expand All @@ -70,8 +87,8 @@ module.exports = class NetworkController extends EventEmitter {

initializeProvider (providerParams) {
this._baseProviderParams = providerParams
const { type, rpcTarget } = this.providerStore.getState()
this._configureProvider({ type, rpcTarget })
const { type, rpcTarget, chainId, ticker, nickname } = this.providerStore.getState()
this._configureProvider({ type, rpcTarget, chainId, ticker, nickname })
this.lookupNetwork()
}

Expand All @@ -91,7 +108,20 @@ module.exports = class NetworkController extends EventEmitter {
return this.networkStore.getState()
}

setNetworkState (network) {
getNetworkConfig () {
return this.networkConfig.getState()
}

setNetworkState (network, type) {
if (network === 'loading') {
return this.networkStore.putState(network)
}

// type must be defined
if (!type) {
return
}
network = networks.networkList[type] && networks.networkList[type].chainId ? networks.networkList[type].chainId : network
return this.networkStore.putState(network)
}

Expand All @@ -100,45 +130,46 @@ module.exports = class NetworkController extends EventEmitter {
}

lookupNetwork () {
const { type, rpcTarget } = this.providerStore.getState()
// Prevent firing when provider is not defined.
if (!this._provider) {
return log.warn('NetworkController - lookupNetwork aborted due to missing provider')
}
const { type, rpcTarget } = this.providerStore.getState()
const ethQuery = new EthQuery(this._provider)
const initialNetwork = this.getNetworkState()
ethQuery.sendAsync({ method: 'net_version' }, (err, network) => {
if (err) return this.setNetworkState('loading')
const targetHost = parse(rpcTarget, true).host
const classicHost = parse(ethNetProps.RPCEndpoints(CLASSIC_CODE)[0], true).host
if (type === CLASSIC || targetHost === classicHost) {
network = CLASSIC_CODE.toString()
} // workaround to avoid Mainnet and Classic are having the same network ID
log.info('web3.getNetwork returned ' + network)
this.setNetworkState(network)
const currentNetwork = this.getNetworkState()
if (initialNetwork === currentNetwork) {
if (err) {
return this.setNetworkState('loading')
}
log.info('web3.getNetwork returned ' + network)
this.setNetworkState(network, type)
}
})
}

setRpcTarget (rpcTarget) {
setRpcTarget (rpcTarget, chainId, ticker = 'ETH', nickname = '', rpcPrefs) {
const providerConfig = {
type: 'rpc',
rpcTarget,
chainId,
ticker,
nickname,
rpcPrefs,
}
this.providerConfig = providerConfig
}

async setProviderType (type) {
async setProviderType (type, rpcTarget = '', ticker = 'ETH', nickname = '') {
assert.notEqual(type, 'rpc', `NetworkController - cannot call "setProviderType" with type 'rpc'. use "setRpcTarget"`)
assert(INFURA_PROVIDER_TYPES.includes(type) ||
type === LOCALHOST ||
type === POA_SOKOL ||
type === POA ||
type === DAI ||
type === GOERLI_TESTNET ||
type === CLASSIC ||
type === RSK ||
type === RSK_TESTNET
, `NetworkController - Unknown rpc type "${type}"`)
const providerConfig = { type }
assert(isKnownProvider(type), `NetworkController - Unknown rpc type "${type}"`)
const providerConfig = { type, rpcTarget, ticker, nickname }
this.providerConfig = providerConfig
}

Expand All @@ -155,11 +186,11 @@ module.exports = class NetworkController extends EventEmitter {
return this.providerStore.getState()
}

getDProvider(){
getDProvider () {
return this.dProviderStore.getState().dProvider
}

setDProvider(key){
setDProvider (key) {
this.dProviderStore.updateState({
dProvider: key,
})
Expand All @@ -172,46 +203,46 @@ module.exports = class NetworkController extends EventEmitter {
_switchNetwork (opts) {
this.setNetworkState('loading')
this._configureProvider(opts)
this.emit('networkDidChange')
this.emit('networkDidChange', opts.type)
}

_configureProvider (opts) {
const { type, rpcTarget } = opts
const { type, rpcTarget, chainId, ticker, nickname } = opts
// infura type-based endpoints
const isInfura = INFURA_PROVIDER_TYPES.includes(type)
// pocket type-based endpointes
const isPocket = POCKET_PROVIDER_TYPES.includes(type)

if (!isPocket && this.dProviderStore.getState().dProvider){
if (!isPocket && this.dProviderStore.getState().dProvider) {
this.dProviderStore.updateState({
dProvider: false
dProvider: false,
})
}

if (isPocket && this.dProviderStore.getState().dProvider){
if (isPocket && this.dProviderStore.getState().dProvider) {
this._configurePocketProvider(opts)
} else if (isInfura) {
this._configureInfuraProvider(opts)
// other type-based rpc endpoints
} else if (type === POA) {
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(POA_CODE)[0] })
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(POA_CODE)[0], chainId, ticker, nickname })
} else if (type === DAI) {
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(DAI_CODE)[0] })
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(DAI_CODE)[0], chainId, ticker, nickname })
} else if (type === POA_SOKOL) {
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(POA_SOKOL_CODE)[0] })
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(POA_SOKOL_CODE)[0], chainId, ticker, nickname })
} else if (type === GOERLI_TESTNET) {
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(GOERLI_TESTNET_CODE)[0] })
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(GOERLI_TESTNET_CODE)[0], chainId, ticker, nickname })
} else if (type === CLASSIC) {
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(CLASSIC_CODE)[0] })
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(CLASSIC_CODE)[0], chainId, ticker, nickname })
} else if (type === RSK) {
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(RSK_CODE)[0] })
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(RSK_CODE)[0], chainId, ticker, nickname })
} else if (type === RSK_TESTNET) {
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(RSK_TESTNET_CODE)[0] })
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(RSK_TESTNET_CODE)[0], chainId, ticker, nickname })
} else if (type === LOCALHOST) {
this._configureLocalhostProvider()
// url-based rpc endpoints
} else if (type === 'rpc') {
this._configureStandardProvider({ rpcUrl: rpcTarget })
this._configureStandardProvider({ rpcUrl: rpcTarget, chainId, ticker, nickname })
} else {
throw new Error(`NetworkController - _configureProvider - unknown type "${type}"`)
}
Expand All @@ -221,6 +252,11 @@ module.exports = class NetworkController extends EventEmitter {
log.info('NetworkController - configureInfuraProvider', type)
const networkClient = createInfuraClient({ network: type })
this._setNetworkClient(networkClient)
// setup networkConfig
var settings = {
ticker: 'ETH',
}
this.networkConfig.putState(settings)
}

_configurePocketProvider ({ type }) {
Expand All @@ -235,9 +271,22 @@ module.exports = class NetworkController extends EventEmitter {
this._setNetworkClient(networkClient)
}

_configureStandardProvider ({ rpcUrl }) {
_configureStandardProvider ({ rpcUrl, chainId, ticker, nickname }) {
log.info('NetworkController - configureStandardProvider', rpcUrl)
const networkClient = createJsonRpcClient({ rpcUrl })
// hack to add a 'rpc' network with chainId
networks.networkList['rpc'] = {
chainId: chainId,
rpcUrl,
ticker: ticker || 'ETH',
nickname,
}
// setup networkConfig
var settings = {
network: chainId,
}
settings = extend(settings, networks.networkList['rpc'])
this.networkConfig.putState(settings)
this._setNetworkClient(networkClient)
}

Expand Down
Loading

0 comments on commit dcf3e6b

Please sign in to comment.