aboutsummaryrefslogblamecommitdiffstats
path: root/app/scripts/controllers/network.js
blob: 82eabb57353486567c28287e279c168b4d5ce377 (plain) (tree)























































































































































                                                                                           
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
    }
  }
}