Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support optional chainId #4516

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions app/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,9 @@
"negativeETH": {
"message": "Can not send negative amounts of ETH."
},
"networkName": {
"message": "$1 Network"
},
"networks": {
"message": "Networks"
},
Expand All @@ -629,6 +632,15 @@
"newRPC": {
"message": "New RPC URL"
},
"optionalChainId": {
"message": "ChainId (optional)"
},
"optionalBlockExplorer": {
"message": "BlockExploer Url (optional)"
},
"optionalSymbol": {
"message": "Symbol (optional)"
},
"next": {
"message": "Next"
},
Expand Down Expand Up @@ -805,6 +817,9 @@
"ropsten": {
"message": "Ropsten Test Network"
},
"classic": {
"message": "Ethereum Classic Network"
},
"rpc": {
"message": "Custom RPC"
},
Expand All @@ -823,6 +838,9 @@
"connectingToRinkeby": {
"message": "Connecting to Rinkeby Test Network"
},
"connectingToClassic": {
"message": "Connecting to Ethereum Classic Network"
},
"connectingToUnknown": {
"message": "Connecting to Unknown Network"
},
Expand Down
468 changes: 468 additions & 0 deletions app/images/etc_logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 27 additions & 5 deletions app/scripts/controllers/currency.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class CurrencyController {
*/
constructor (opts = {}) {
const initState = extend({
fromCurrency: 'ETH',
currentCurrency: 'usd',
conversionRate: 0,
conversionDate: 'N/A',
Expand All @@ -36,6 +37,26 @@ class CurrencyController {
// PUBLIC METHODS
//

/**
* A getter for the fromCurrency property
*
* @returns {string} A 2-4 character shorthand that describes the specific currency
*
*/
getFromCurrency () {
return this.store.getState().fromCurrency
}

/**
* A setter for the fromCurrency property
*
* @param {string} fromCurrency The new currency to set as the fromCurrency in the store
*
*/
setFromCurrency (fromCurrency) {
this.store.updateState({ fromCurrency })
}

/**
* A getter for the currentCurrency property
*
Expand Down Expand Up @@ -104,15 +125,16 @@ class CurrencyController {
*
*/
async updateConversionRate () {
let currentCurrency
let currentCurrency, fromCurrency
try {
currentCurrency = this.getCurrentCurrency()
const response = await fetch(`https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}`)
fromCurrency = this.getFromCurrency()
const response = await fetch(`https://min-api.cryptocompare.com/data/pricehistorical?fsym=${fromCurrency.toUpperCase()}&tsyms=${currentCurrency.toUpperCase()}`)
const parsedResponse = await response.json()
this.setConversionRate(Number(parsedResponse.bid))
this.setConversionDate(Number(parsedResponse.timestamp))
this.setConversionRate(Number(parsedResponse[fromCurrency.toUpperCase()][currentCurrency.toUpperCase()]))
this.setConversionDate(parseInt(new Date().getTime() / 1000))
} catch (err) {
log.warn(`MetaMask - Failed to query currency conversion:`, currentCurrency, err)
log.warn(`MetaMask - Failed to query currency conversion:`, fromCurrency, currentCurrency, err)
this.setConversionRate(0)
this.setConversionDate('N/A')
}
Expand Down
6 changes: 6 additions & 0 deletions app/scripts/controllers/network/enums.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,35 @@ const RINKEBY = 'rinkeby'
const KOVAN = 'kovan'
const MAINNET = 'mainnet'
const LOCALHOST = 'localhost'
const CLASSIC = 'classic'

const MAINNET_CODE = 1
const ROPSTEN_CODE = 3
const RINKEYBY_CODE = 4
const KOVAN_CODE = 42
const CLASSIC_CODE = 61

const ROPSTEN_DISPLAY_NAME = 'Ropsten'
const RINKEBY_DISPLAY_NAME = 'Rinkeby'
const KOVAN_DISPLAY_NAME = 'Kovan'
const MAINNET_DISPLAY_NAME = 'Main Ethereum Network'
const CLASSIC_DISPLAY_NAME = 'Ethereum Classic'

module.exports = {
ROPSTEN,
RINKEBY,
KOVAN,
MAINNET,
CLASSIC,
LOCALHOST,
MAINNET_CODE,
ROPSTEN_CODE,
RINKEYBY_CODE,
KOVAN_CODE,
CLASSIC_CODE,
ROPSTEN_DISPLAY_NAME,
RINKEBY_DISPLAY_NAME,
KOVAN_DISPLAY_NAME,
MAINNET_DISPLAY_NAME,
CLASSIC_DISPLAY_NAME,
}
109 changes: 96 additions & 13 deletions app/scripts/controllers/network/network.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@ const extend = require('xtend')
const EthQuery = require('eth-query')
const createEventEmitterProxy = require('../../lib/events-proxy.js')
const log = require('loglevel')
const networks = require('./networks')

const {
ROPSTEN,
RINKEBY,
KOVAN,
MAINNET,
CLASSIC,
LOCALHOST,
} = require('./enums')
const LOCALHOST_RPC_URL = 'http://localhost:8545'
const INFURA_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN, MAINNET]
const ALL_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN, MAINNET, CLASSIC]

const env = process.env.METAMASK_ENV
const METAMASK_DEBUG = process.env.METAMASK_DEBUG
Expand All @@ -27,6 +31,10 @@ const defaultProviderConfig = {
type: testMode ? RINKEBY : MAINNET,
}

const defaultNetworkConfig = {
type: 'mainnet', ticker: 'ETH',
}

module.exports = class NetworkController extends EventEmitter {

constructor (opts = {}) {
Expand All @@ -37,7 +45,8 @@ module.exports = class NetworkController extends EventEmitter {
// create stores
this.providerStore = new ObservableStore(providerConfig)
this.networkStore = new ObservableStore('loading')
this.store = new ComposedStore({ provider: this.providerStore, network: this.networkStore })
this.networkConfig = new ObservableStore(defaultNetworkConfig)
this.store = new ComposedStore({ provider: this.providerStore, network: this.networkStore, settings: this.networkConfig })
// create event emitter proxy
this._proxy = createEventEmitterProxy()

Expand All @@ -46,55 +55,79 @@ 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, explorerUrl, symbol } = this.providerStore.getState()
this._configureProvider({ type, rpcTarget, chainId, explorerUrl, symbol })
this._proxy.on('block', this._logBlock.bind(this))
this._proxy.on('error', this.verifyNetwork.bind(this))
this.ethQuery = new EthQuery(this._proxy)
this.lookupNetwork()
this.lookupNetwork(type)
return this._proxy
}

verifyNetwork () {
// Check network when restoring connectivity:
if (this.isNetworkLoading()) this.lookupNetwork()
const { type } = this.providerStore.getState()
if (this.isNetworkLoading()) this.lookupNetwork(type)
}

getNetworkState () {
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
console.info('type = ' + type + ', network (chainId) = ' + network)
return this.networkStore.putState(network)
}

isNetworkLoading () {
return this.getNetworkState() === 'loading'
}

lookupNetwork () {
lookupNetwork (newtype) {
// Prevent firing when provider is not defined.
if (!this.ethQuery || !this.ethQuery.sendAsync) {
return log.warn('NetworkController - lookupNetwork aborted due to missing ethQuery')
}
var { type } = this.providerStore.getState()
if (!newtype) {
newtype = type
}

this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => {
if (err) return this.setNetworkState('loading')
log.info('web3.getNetwork returned ' + network)
this.setNetworkState(network)
console.info('type = ' + newtype + ' / web3.getNetwork returned ' + network)
this.setNetworkState(network, newtype)
})
}

setRpcTarget (rpcTarget) {
setRpcTarget (rpcTarget, chainId, explorerUrl, symbol) {
const providerConfig = {
type: 'rpc',
rpcTarget,
chainId,
explorerUrl,
symbol,
}
this.providerConfig = providerConfig
}

async setProviderType (type) {
assert.notEqual(type, 'rpc', `NetworkController - cannot call "setProviderType" with type 'rpc'. use "setRpcTarget"`)
assert(INFURA_PROVIDER_TYPES.includes(type) || type === LOCALHOST, `NetworkController - Unknown rpc type "${type}"`)
assert(ALL_PROVIDER_TYPES.includes(type) || type === LOCALHOST, `NetworkController - Unknown rpc type "${type}"`)
const providerConfig = { type }
this.providerConfig = providerConfig
}
Expand Down Expand Up @@ -123,17 +156,20 @@ module.exports = class NetworkController extends EventEmitter {
}

_configureProvider (opts) {
const { type, rpcTarget } = opts
const { type, rpcTarget, chainId, explorerUrl, symbol } = opts
// infura type-based endpoints
const isInfura = INFURA_PROVIDER_TYPES.includes(type)
if (isInfura) {
this._configureInfuraProvider(opts)
// other predefined endpoints
} else if (ALL_PROVIDER_TYPES.includes(type)){
this._configurePredefinedProvider(opts)
// other type-based rpc endpoints
} else if (type === LOCALHOST) {
this._configureStandardProvider({ rpcUrl: LOCALHOST_RPC_URL })
// url-based rpc endpoints
} else if (type === 'rpc') {
this._configureStandardProvider({ rpcUrl: rpcTarget })
this._configureStandardProvider({ rpcUrl: rpcTarget, chainId, explorerUrl, symbol })
} else {
throw new Error(`NetworkController - _configureProvider - unknown type "${type}"`)
}
Expand All @@ -150,17 +186,64 @@ module.exports = class NetworkController extends EventEmitter {
},
dataSubprovider: infuraSubprovider,
})
// setup networkConfig
var settings = {
type,
ticker: 'ETH',
}
this.networkConfig.putState(settings)
const provider = createMetamaskProvider(providerParams)
this._setProvider(provider)
}

_configureStandardProvider ({ rpcUrl }) {
_configurePredefinedProvider ({ type }) {
log.info('_configurePredefinedProvider', type)
const providerParams = extend(this._baseProviderParams, {
type,
rpcUrl: networks.networkList[type].rpcUrl,
engineParams: {
pollingInterval: networks.networkList[type].pollingInterval || 8000,
},
})
// setup networkConfig
if (networks.networkList[type]) {
var settings = {
type,
network: networks.networkList[type].chainId,
}
settings = extend(settings, networks.networkList[type])
this.networkConfig.putState(settings)
}
const provider = createMetamaskProvider(providerParams)
this._setProvider(provider)
}

_configureStandardProvider ({ rpcUrl, chainId, explorerUrl, symbol }) {
const providerParams = extend(this._baseProviderParams, {
rpcUrl,
engineParams: {
pollingInterval: 8000,
},
})
// hack to add a 'rpc' network with chainId
networks.networkList['rpc'] = {
chainId: chainId,
rpcUrl,
ticker: symbol || 'ETH',
}
// setup networkConfig
var settings = {
type: 'rpc',
network: chainId,
ticker: symbol || 'ETH',
}
if (explorerUrl) {
settings.blockExplorerTx = explorerUrl + '/tx/[[txHash]]'
settings.blockExplorerAddr = explorerUrl + '/addr/[[address]]'
settings.blockExplorerToken = explorerUrl + '/token/[[tokenAddress]]/[[address]]'
}
settings = extend(settings, networks.networkList['rpc'])
this.networkConfig.putState(settings)
const provider = createMetamaskProvider(providerParams)
this._setProvider(provider)
}
Expand Down
23 changes: 23 additions & 0 deletions app/scripts/controllers/network/networks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use strict'
var networks = function() {}

const {
CLASSIC,
CLASSIC_CODE,
} = require('./enums')

networks.networkList = {
[CLASSIC]: {
'chainId': CLASSIC_CODE,
'ticker': 'ETC',
'blockExplorerTx': 'https://gastracker.io/tx/[[txHash]]',
'blockExplorerAddr': 'https://gastracker.io/addr/[[address]]',
'blockExplorerToken': 'https://gastracker.io/token/[[tokenAddress]]/[[address]]',
'service': 'Ethereum Commonwealth',
'rpcUrl': 'https://etc-geth.0xinfra.com',
Copy link
Contributor Author

@hackmod hackmod Jun 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where can I find api server for the modern testnet?

https://web3.gastracker.io/morden not correctly work...

'exchanges': ['ShapeShift'],
'buyUrl': '',
},
}

module.exports = networks
Loading