aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfrankiebee <frankie.diamond@gmail.com>2017-05-19 05:54:02 +0800
committerfrankiebee <frankie.diamond@gmail.com>2017-05-19 06:14:10 +0800
commitf87ea49b5ac2d66d8f281f08f42e8cfd2d701ba7 (patch)
tree349903e455ddeccb64b913b12c950e5f5548d046
parent03d454f73baa27f9b44ec4bee0ba8f3c71414aa6 (diff)
downloadtangerine-wallet-browser-f87ea49b5ac2d66d8f281f08f42e8cfd2d701ba7.tar
tangerine-wallet-browser-f87ea49b5ac2d66d8f281f08f42e8cfd2d701ba7.tar.gz
tangerine-wallet-browser-f87ea49b5ac2d66d8f281f08f42e8cfd2d701ba7.tar.bz2
tangerine-wallet-browser-f87ea49b5ac2d66d8f281f08f42e8cfd2d701ba7.tar.lz
tangerine-wallet-browser-f87ea49b5ac2d66d8f281f08f42e8cfd2d701ba7.tar.xz
tangerine-wallet-browser-f87ea49b5ac2d66d8f281f08f42e8cfd2d701ba7.tar.zst
tangerine-wallet-browser-f87ea49b5ac2d66d8f281f08f42e8cfd2d701ba7.zip
Create a network controller to manage switcing networks an updating the provider
-rw-r--r--app/scripts/controllers/network.js152
-rw-r--r--app/scripts/keyring-controller.js6
-rw-r--r--app/scripts/lib/config-manager.js67
-rw-r--r--app/scripts/lib/tx-utils.js8
-rw-r--r--app/scripts/metamask-controller.js124
-rw-r--r--app/scripts/transaction-manager.js25
6 files changed, 232 insertions, 150 deletions
diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js
new file mode 100644
index 000000000..82eabb573
--- /dev/null
+++ b/app/scripts/controllers/network.js
@@ -0,0 +1,152 @@
+const EventEmitter = require('events')
+const MetaMaskProvider = require('web3-provider-engine/zero.js')
+const ObservableStore = require('obs-store')
+const extend = require('xtend')
+const EthQuery = require('eth-query')
+const MetamaskConfig = require('../config.js')
+
+const TESTNET_RPC = MetamaskConfig.network.testnet
+const MAINNET_RPC = MetamaskConfig.network.mainnet
+const MORDEN_RPC = MetamaskConfig.network.morden
+const KOVAN_RPC = MetamaskConfig.network.kovan
+const RINKEBY_RPC = MetamaskConfig.network.rinkeby
+
+module.exports = class NetworkController extends EventEmitter {
+ constructor (providerOpts) {
+ super()
+ this.networkStore = new ObservableStore({ network: 'loading' })
+ providerOpts.provider.rpcTarget = this.getRpcAddressForType(providerOpts.provider.type)
+ this.providerStore = new ObservableStore(providerOpts)
+ this._claimed = 0
+ }
+
+ getState () {
+ return extend({},
+ this.networkStore.getState(),
+ this.providerStore.getState()
+ )
+ }
+
+ initializeProvider (opts) {
+ this.providerConfig = opts
+ this.provider = MetaMaskProvider(opts)
+ this.ethQuery = new EthQuery(this.provider)
+ this.lookupNetwork()
+ return Promise.resolve(this.provider)
+ }
+ switchNetwork (providerConfig) {
+ delete this.provider
+ delete this.ethQuery
+ const newConfig = extend(this.providerConfig, providerConfig)
+ this.providerConfig = newConfig
+ this.provider = MetaMaskProvider(newConfig)
+ this.ethQuery = new EthQuery(this.provider)
+ this.emit('networkSwitch', {
+ provider: this.provider,
+ ethQuery: this.ethQuery,
+ }, this.claim.bind(this))
+ }
+
+ subscribe (cb) {
+ this.networkStore.subscribe(cb)
+ this.providerStore.subscribe(cb)
+ }
+
+ verifyNetwork () {
+ // Check network when restoring connectivity:
+ if (this.isNetworkLoading()) this.lookupNetwork()
+ }
+
+ getNetworkState () {
+ return this.networkStore.getState().network
+ }
+
+ setNetworkState (network) {
+ return this.networkStore.updateState({ network })
+ }
+
+ isNetworkLoading () {
+ return this.getNetworkState() === 'loading'
+ }
+
+ lookupNetwork (err) {
+ if (err) this.setNetworkState('loading')
+
+ this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => {
+ if (err) return this.setNetworkState('loading')
+
+ log.info('web3.getNetwork returned ' + network)
+ this.setNetworkState(network)
+ })
+ }
+
+ setRpcTarget (rpcUrl) {
+ this.providerStore.updateState({
+ provider: {
+ type: 'rpc',
+ rpcTarget: rpcUrl,
+ },
+ })
+ }
+
+ getCurrentRpcAddress () {
+ var provider = this.getProvider()
+ if (!provider) return null
+ return this.getRpcAddressForType(provider.type)
+ }
+
+ setProviderType (type) {
+ if (type === this.getProvider().type) return
+ const rpcTarget = this.getRpcAddressForType(type)
+ this.networkStore.updateState({network: 'loading'})
+ this.switchNetwork({
+ rpcUrl: rpcTarget,
+ })
+ this.once('claimed', () => {
+ this.providerStore.updateState({provider: {type, rpcTarget}})
+ console.log('CLAIMED')
+ this.lookupNetwork()
+ })
+
+ }
+
+ useEtherscanProvider () {
+ this.setProviderType('etherscan')
+ }
+
+ getProvider () {
+ return this.providerStore.getState().provider
+ }
+
+ getRpcAddressForType (type) {
+ const provider = this.getProvider()
+ switch (type) {
+
+ case 'mainnet':
+ return MAINNET_RPC
+
+ case 'testnet':
+ return TESTNET_RPC
+
+ case 'morden':
+ return MORDEN_RPC
+
+ case 'kovan':
+ return KOVAN_RPC
+
+ case 'rinkeby':
+ return RINKEBY_RPC
+
+ default:
+ return provider && provider.rpcTarget ? provider.rpcTarget : TESTNET_RPC
+ }
+ }
+
+ claim () {
+ this._claimed += 1
+ if (this._claimed === this.listenerCount('networkSwitch')) {
+ this.emit('claimed')
+ this._claimed = 0
+ }
+ }
+}
diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js
index 5b3c80e40..bb699ca8b 100644
--- a/app/scripts/keyring-controller.js
+++ b/app/scripts/keyring-controller.js
@@ -41,6 +41,12 @@ class KeyringController extends EventEmitter {
this.getNetwork = opts.getNetwork
}
+ setEthStore (ethStore) {
+ delete this.ethStore
+ this.ethStore = ethStore
+ return this.setupAccounts()
+ }
+
// Full Update
// returns Promise( @object state )
//
diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js
index ab9410842..1098cc474 100644
--- a/app/scripts/lib/config-manager.js
+++ b/app/scripts/lib/config-manager.js
@@ -1,14 +1,6 @@
-const MetamaskConfig = require('../config.js')
const ethUtil = require('ethereumjs-util')
const normalize = require('eth-sig-util').normalize
-const TESTNET_RPC = MetamaskConfig.network.testnet
-const MAINNET_RPC = MetamaskConfig.network.mainnet
-const MORDEN_RPC = MetamaskConfig.network.morden
-const KOVAN_RPC = MetamaskConfig.network.kovan
-const RINKEBY_RPC = MetamaskConfig.network.rinkeby
-
-
/* The config-manager is a convenience object
* wrapping a pojo-migrator.
*
@@ -35,36 +27,6 @@ ConfigManager.prototype.getConfig = function () {
return data.config
}
-ConfigManager.prototype.setRpcTarget = function (rpcUrl) {
- var config = this.getConfig()
- config.provider = {
- type: 'rpc',
- rpcTarget: rpcUrl,
- }
- this.setConfig(config)
-}
-
-ConfigManager.prototype.setProviderType = function (type) {
- var config = this.getConfig()
- config.provider = {
- type: type,
- }
- this.setConfig(config)
-}
-
-ConfigManager.prototype.useEtherscanProvider = function () {
- var config = this.getConfig()
- config.provider = {
- type: 'etherscan',
- }
- this.setConfig(config)
-}
-
-ConfigManager.prototype.getProvider = function () {
- var config = this.getConfig()
- return config.provider
-}
-
ConfigManager.prototype.setData = function (data) {
this.store.putState(data)
}
@@ -139,35 +101,6 @@ ConfigManager.prototype.getSeedWords = function () {
return data.seedWords
}
-ConfigManager.prototype.getCurrentRpcAddress = function () {
- var provider = this.getProvider()
- if (!provider) return null
- switch (provider.type) {
-
- case 'mainnet':
- return MAINNET_RPC
-
- case 'testnet':
- return TESTNET_RPC
-
- case 'morden':
- return MORDEN_RPC
-
- case 'kovan':
- return KOVAN_RPC
-
- case 'rinkeby':
- return RINKEBY_RPC
-
- default:
- return provider && provider.rpcTarget ? provider.rpcTarget : TESTNET_RPC
- }
-}
-
-//
-// Tx
-//
-
ConfigManager.prototype.getTxList = function () {
var data = this.getData()
if (data.transactions !== undefined) {
diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js
index 084ca3721..76b311653 100644
--- a/app/scripts/lib/tx-utils.js
+++ b/app/scripts/lib/tx-utils.js
@@ -1,5 +1,4 @@
const async = require('async')
-const EthQuery = require('eth-query')
const ethUtil = require('ethereumjs-util')
const Transaction = require('ethereumjs-tx')
const normalize = require('eth-sig-util').normalize
@@ -7,15 +6,14 @@ const BN = ethUtil.BN
/*
tx-utils are utility methods for Transaction manager
-its passed a provider and that is passed to ethquery
+its passed ethquery
and used to do things like calculate gas of a tx.
*/
module.exports = class txProviderUtils {
- constructor (provider) {
- this.provider = provider
- this.query = new EthQuery(provider)
+ constructor (ethQuery) {
+ this.query = ethQuery
}
analyzeGasUsage (txMeta, cb) {
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index 175602ec1..71293d05f 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -7,9 +7,9 @@ const ObservableStore = require('obs-store')
const EthStore = require('./lib/eth-store')
const EthQuery = require('eth-query')
const streamIntoProvider = require('web3-stream-provider/handler')
-const MetaMaskProvider = require('web3-provider-engine/zero.js')
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
const KeyringController = require('./keyring-controller')
+const NetworkController = require('./controllers/network')
const PreferencesController = require('./controllers/preferences')
const CurrencyController = require('./controllers/currency')
const NoticeController = require('./notice-controller')
@@ -40,8 +40,7 @@ module.exports = class MetamaskController extends EventEmitter {
this.store = new ObservableStore(initState)
// network store
- this.networkStore = new ObservableStore({ network: 'loading' })
-
+ this.networkController = new NetworkController(initState.NetworkController)
// config manager
this.configManager = new ConfigManager({
store: this.store,
@@ -62,7 +61,7 @@ module.exports = class MetamaskController extends EventEmitter {
// rpc provider
this.provider = this.initializeProvider()
this.provider.on('block', this.logBlock.bind(this))
- this.provider.on('error', this.verifyNetwork.bind(this))
+ this.provider.on('error', this.networkController.verifyNetwork.bind(this.networkController))
// eth data query tools
this.ethQuery = new EthQuery(this.provider)
@@ -75,7 +74,7 @@ module.exports = class MetamaskController extends EventEmitter {
this.keyringController = new KeyringController({
initState: initState.KeyringController,
ethStore: this.ethStore,
- getNetwork: this.getNetworkState.bind(this),
+ getNetwork: this.networkController.getNetworkState.bind(this.networkController),
})
this.keyringController.on('newAccount', (address) => {
this.preferencesController.setSelectedAddress(address)
@@ -92,10 +91,10 @@ module.exports = class MetamaskController extends EventEmitter {
// tx mgmt
this.txManager = new TxManager({
initState: initState.TransactionManager,
- networkStore: this.networkStore,
+ networkStore: this.networkController.networkStore,
preferencesStore: this.preferencesController.store,
txHistoryLimit: 40,
- getNetwork: this.getNetworkState.bind(this),
+ getNetwork: this.networkController.getNetworkState.bind(this),
signTransaction: this.keyringController.signTransaction.bind(this.keyringController),
provider: this.provider,
blockTracker: this.provider,
@@ -112,8 +111,34 @@ module.exports = class MetamaskController extends EventEmitter {
this.shapeshiftController = new ShapeShiftController({
initState: initState.ShapeShiftController,
})
+ this.networkController.on('networkSwitch', (providerUtil, claimed) => {
+ delete this.provider
+ delete this.ethQuery
+ delete this.ethStore
+ console.log('order:@? 1')
+ this.provider = providerUtil.provider
+ this.provider.on('block', this.logBlock.bind(this))
+ this.provider.on('error', this.networkController.verifyNetwork.bind(this.networkController))
+
+ this.ethQuery = providerUtil.ethQuery
+ this.ethStore = new EthStore({
+ provider: this.provider,
+ blockTracker: this.provider,
+ })
+ this.provider.once('block', claimed)
+ })
+ this.networkController.on('networkSwitch', (_, claimed) => {
+ console.log('order:@? 2')
+ this.txManager.setupProviderAndEthQuery({
+ provider: this.provider,
+ blockTracker: this.provider,
+ ethQuery: this.ethQuery,
+ })
+ this.keyringController.setEthStore(this.ethStore)
+ .then(claimed)
+ })
- this.lookupNetwork()
+ this.networkController.lookupNetwork()
this.messageManager = new MessageManager()
this.personalMessageManager = new PersonalMessageManager()
this.publicConfigStore = this.initPublicConfigStore()
@@ -140,9 +165,12 @@ module.exports = class MetamaskController extends EventEmitter {
this.shapeshiftController.store.subscribe((state) => {
this.store.updateState({ ShapeShiftController: state })
})
+ this.networkController.providerStore.subscribe((state) => {
+ this.store.updateState({ NetworkController: state })
+ })
// manual mem state subscriptions
- this.networkStore.subscribe(this.sendUpdate.bind(this))
+ this.networkController.subscribe(this.sendUpdate.bind(this))
this.ethStore.subscribe(this.sendUpdate.bind(this))
this.txManager.memStore.subscribe(this.sendUpdate.bind(this))
this.messageManager.memStore.subscribe(this.sendUpdate.bind(this))
@@ -160,12 +188,12 @@ module.exports = class MetamaskController extends EventEmitter {
//
initializeProvider () {
- const provider = MetaMaskProvider({
+ this.networkController.initializeProvider({
static: {
eth_syncing: false,
web3_clientVersion: `MetaMask/v${version}`,
},
- rpcUrl: this.configManager.getCurrentRpcAddress(),
+ rpcUrl: this.networkController.getCurrentRpcAddress(),
// account mgmt
getAccounts: (cb) => {
const isUnlocked = this.keyringController.memStore.getState().isUnlocked
@@ -185,7 +213,7 @@ module.exports = class MetamaskController extends EventEmitter {
// new style msg signing
processPersonalMessage: this.newUnsignedPersonalMessage.bind(this),
})
- return provider
+ return this.networkController.provider
}
initPublicConfigStore () {
@@ -221,7 +249,7 @@ module.exports = class MetamaskController extends EventEmitter {
{
isInitialized,
},
- this.networkStore.getState(),
+ this.networkController.getState(),
this.ethStore.getState(),
this.txManager.memStore.getState(),
this.messageManager.memStore.getState(),
@@ -255,8 +283,8 @@ module.exports = class MetamaskController extends EventEmitter {
return {
// etc
getState: (cb) => cb(null, this.getState()),
- setProviderType: this.setProviderType.bind(this),
- useEtherscanProvider: this.useEtherscanProvider.bind(this),
+ setProviderType: this.networkController.setProviderType.bind(this.networkController),
+ useEtherscanProvider: this.networkController.useEtherscanProvider.bind(this.networkController),
setCurrentCurrency: this.setCurrentCurrency.bind(this),
markAccountsFound: this.markAccountsFound.bind(this),
// coinbase
@@ -592,7 +620,7 @@ module.exports = class MetamaskController extends EventEmitter {
// Log blocks
logBlock (block) {
log.info(`BLOCK CHANGED: #${block.number.toString('hex')} 0x${block.hash.toString('hex')}`)
- this.verifyNetwork()
+ this.networkController.verifyNetwork()
}
setCurrentCurrency (currencyCode, cb) {
@@ -612,7 +640,7 @@ module.exports = class MetamaskController extends EventEmitter {
buyEth (address, amount) {
if (!amount) amount = '5'
- const network = this.getNetworkState()
+ const network = this.networkController.getNetworkState()
const url = getBuyEthUrl({ network, address, amount })
if (url) this.platform.openWindow({ url })
}
@@ -620,69 +648,21 @@ module.exports = class MetamaskController extends EventEmitter {
createShapeShiftTx (depositAddress, depositType) {
this.shapeshiftController.createShapeShiftTx(depositAddress, depositType)
}
-
- //
- // network
- //
-
- verifyNetwork () {
- // Check network when restoring connectivity:
- if (this.isNetworkLoading()) this.lookupNetwork()
- }
+// network
setDefaultRpc () {
- this.configManager.setRpcTarget('http://localhost:8545')
- this.platform.reload()
- this.lookupNetwork()
+ this.networkController.setRpcTarget('http://localhost:8545')
return Promise.resolve('http://localhost:8545')
}
setCustomRpc (rpcTarget, rpcList) {
- this.configManager.setRpcTarget(rpcTarget)
- return this.preferencesController.updateFrequentRpcList(rpcTarget)
- .then(() => {
- this.platform.reload()
- this.lookupNetwork()
- return Promise.resolve(rpcTarget)
- })
- }
-
- setProviderType (type) {
- this.configManager.setProviderType(type)
- this.platform.reload()
- this.lookupNetwork()
- }
-
- useEtherscanProvider () {
- this.configManager.useEtherscanProvider()
- this.platform.reload()
- }
-
- getNetworkState () {
- return this.networkStore.getState().network
- }
-
- setNetworkState (network) {
- return this.networkStore.updateState({ network })
- }
+ this.networkController.setRpcTarget(rpcTarget)
- isNetworkLoading () {
- return this.getNetworkState() === 'loading'
- }
-
- lookupNetwork (err) {
- if (err) {
- this.setNetworkState('loading')
- }
-
- this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => {
- if (err) {
- this.setNetworkState('loading')
- return
- }
- log.info('web3.getNetwork returned ' + network)
- this.setNetworkState(network)
+ return this.preferencesController.updateFrequentRpcList(rpcTarget)
+ .then(() => {
+ return Promise.resolve(rpcTarget)
})
}
+
}
diff --git a/app/scripts/transaction-manager.js b/app/scripts/transaction-manager.js
index 9f267160f..1e15128f9 100644
--- a/app/scripts/transaction-manager.js
+++ b/app/scripts/transaction-manager.js
@@ -4,7 +4,6 @@ const extend = require('xtend')
const Semaphore = require('semaphore')
const ObservableStore = require('obs-store')
const ethUtil = require('ethereumjs-util')
-const EthQuery = require('eth-query')
const TxProviderUtil = require('./lib/tx-utils')
const createId = require('./lib/random-id')
@@ -18,11 +17,11 @@ module.exports = class TransactionManager extends EventEmitter {
this.networkStore = opts.networkStore || new ObservableStore({})
this.preferencesStore = opts.preferencesStore || new ObservableStore({})
this.txHistoryLimit = opts.txHistoryLimit
- this.provider = opts.provider
- this.blockTracker = opts.blockTracker
- this.query = new EthQuery(this.provider)
- this.txProviderUtils = new TxProviderUtil(this.provider)
- this.blockTracker.on('block', this.checkForTxInBlock.bind(this))
+ this.setupProviderAndEthQuery({
+ provider: opts.provider,
+ blockTracker: opts.blockTracker,
+ ethQuery: opts.ethQuery,
+ })
this.signEthTx = opts.signTransaction
this.nonceLock = Semaphore(1)
@@ -41,6 +40,20 @@ module.exports = class TransactionManager extends EventEmitter {
return this.networkStore.getState().network
}
+ setupProviderAndEthQuery ({provider, blockTracker, ethQuery}) {
+ if (this.provider) {
+ delete this.provider
+ delete this.blockTracker
+ delete this.query
+ delete this.txProviderUtils
+ }
+ this.provider = provider
+ this.query = ethQuery
+ this.txProviderUtils = new TxProviderUtil(ethQuery)
+ blockTracker ? this.blockTracker = blockTracker : this.blockTracker = provider
+ this.blockTracker.on('block', this.checkForTxInBlock.bind(this))
+ }
+
getSelectedAddress () {
return this.preferencesStore.getState().selectedAddress
}