diff options
Merge branch 'develop' of github.com:MetaMask/metamask-extension into sentry-enhancements2
Diffstat (limited to 'app/scripts')
-rw-r--r-- | app/scripts/background.js | 10 | ||||
-rw-r--r-- | app/scripts/controllers/currency.js | 58 | ||||
-rw-r--r-- | app/scripts/controllers/network/createMetamaskMiddleware.js | 2 | ||||
-rw-r--r-- | app/scripts/controllers/network/network.js | 76 | ||||
-rw-r--r-- | app/scripts/controllers/preferences.js | 33 | ||||
-rw-r--r-- | app/scripts/lib/ens-ipfs/contracts/registrar.js (renamed from app/scripts/lib/contracts/registrar.js) | 0 | ||||
-rw-r--r-- | app/scripts/lib/ens-ipfs/contracts/resolver.js (renamed from app/scripts/lib/contracts/resolver.js) | 0 | ||||
-rw-r--r-- | app/scripts/lib/ens-ipfs/resolver.js | 54 | ||||
-rw-r--r-- | app/scripts/lib/ens-ipfs/setup.js | 63 | ||||
-rw-r--r-- | app/scripts/lib/ipfsContent.js | 46 | ||||
-rw-r--r-- | app/scripts/lib/resolver.js | 71 | ||||
-rw-r--r-- | app/scripts/metamask-controller.js | 49 |
12 files changed, 275 insertions, 187 deletions
diff --git a/app/scripts/background.js b/app/scripts/background.js index 2455608aa..2a3c5b08b 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -29,7 +29,7 @@ const setupMetamaskMeshMetrics = require('./lib/setupMetamaskMeshMetrics') const EdgeEncryptor = require('./edge-encryptor') const getFirstPreferredLangCode = require('./lib/get-first-preferred-lang-code') const getObjStructure = require('./lib/getObjStructure') -const ipfsContent = require('./lib/ipfsContent.js') +const setupEnsIpfsResolver = require('./lib/ens-ipfs/setup') const { ENVIRONMENT_TYPE_POPUP, @@ -58,7 +58,6 @@ const isIE = !!document.documentMode // Edge 20+ const isEdge = !isIE && !!window.StyleMedia -let ipfsHandle let popupIsOpen = false let notificationIsOpen = false const openMetamaskTabsIDs = {} @@ -164,7 +163,6 @@ async function initialize () { const initLangCode = await getFirstPreferredLangCode() await setupController(initState, initLangCode) log.debug('MetaMask initialization complete.') - ipfsHandle = ipfsContent(initState.NetworkController.provider) } // @@ -269,10 +267,8 @@ function setupController (initState, initLangCode) { }) global.metamaskController = controller - controller.networkController.on('networkDidChange', () => { - ipfsHandle && ipfsHandle.remove() - ipfsHandle = ipfsContent(controller.networkController.providerStore.getState()) - }) + const provider = controller.provider + setupEnsIpfsResolver({ provider }) // report failed transactions to Sentry controller.txController.on(`tx:status-update`, (txId, status) => { diff --git a/app/scripts/controllers/currency.js b/app/scripts/controllers/currency.js index 6b82265f6..cc78ef8a6 100644 --- a/app/scripts/controllers/currency.js +++ b/app/scripts/controllers/currency.js @@ -21,6 +21,7 @@ class CurrencyController { * since midnight of January 1, 1970 * @property {number} conversionInterval The id of the interval created by the scheduleConversionInterval method. * Used to clear an existing interval on subsequent calls of that method. + * @property {string} nativeCurrency The ticker/symbol of the native chain currency * */ constructor (opts = {}) { @@ -28,6 +29,7 @@ class CurrencyController { currentCurrency: 'usd', conversionRate: 0, conversionDate: 'N/A', + nativeCurrency: 'ETH', }, opts.initState) this.store = new ObservableStore(initState) } @@ -37,6 +39,29 @@ class CurrencyController { // /** + * A getter for the nativeCurrency property + * + * @returns {string} A 2-4 character shorthand that describes the specific currency + * + */ + getNativeCurrency () { + return this.store.getState().nativeCurrency + } + + /** + * A setter for the nativeCurrency property + * + * @param {string} nativeCurrency The new currency to set as the nativeCurrency in the store + * + */ + setNativeCurrency (nativeCurrency) { + this.store.updateState({ + nativeCurrency, + ticker: nativeCurrency, + }) + } + + /** * A getter for the currentCurrency property * * @returns {string} A 2-4 character shorthand that describes a specific currency, currently selected by the user @@ -104,16 +129,28 @@ class CurrencyController { * */ async updateConversionRate () { - let currentCurrency + let currentCurrency, nativeCurrency try { currentCurrency = this.getCurrentCurrency() + nativeCurrency = this.getNativeCurrency() + // select api + let apiUrl + if (nativeCurrency === 'ETH') { + // ETH + apiUrl = `https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}` + } else { + // ETC + apiUrl = `https://min-api.cryptocompare.com/data/price?fsym=${nativeCurrency.toUpperCase()}&tsyms=${currentCurrency.toUpperCase()}` + } + // attempt request let response try { - response = await fetch(`https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}`) + response = await fetch(apiUrl) } catch (err) { log.error(new Error(`CurrencyController - Failed to request currency from Infura:\n${err.stack}`)) return } + // parse response let rawResponse let parsedResponse try { @@ -123,8 +160,21 @@ class CurrencyController { log.error(new Error(`CurrencyController - Failed to parse response "${rawResponse}"`)) return } - this.setConversionRate(Number(parsedResponse.bid)) - this.setConversionDate(Number(parsedResponse.timestamp)) + // set exhcange rate + if (nativeCurrency === 'ETH') { + // ETH + this.setConversionRate(Number(parsedResponse.bid)) + this.setConversionDate(Number(parsedResponse.timestamp)) + } else { + // ETC + if (parsedResponse[currentCurrency.toUpperCase()]) { + this.setConversionRate(Number(parsedResponse[currentCurrency.toUpperCase()])) + this.setConversionDate(parseInt((new Date()).getTime() / 1000)) + } else { + this.setConversionRate(0) + this.setConversionDate('N/A') + } + } } catch (err) { // reset current conversion rate this.setConversionRate(0) diff --git a/app/scripts/controllers/network/createMetamaskMiddleware.js b/app/scripts/controllers/network/createMetamaskMiddleware.js index 9e6a45888..319c5bf3e 100644 --- a/app/scripts/controllers/network/createMetamaskMiddleware.js +++ b/app/scripts/controllers/network/createMetamaskMiddleware.js @@ -11,6 +11,7 @@ function createMetamaskMiddleware ({ processTransaction, processEthSignMessage, processTypedMessage, + processTypedMessageV3, processPersonalMessage, getPendingNonce, }) { @@ -25,6 +26,7 @@ function createMetamaskMiddleware ({ processTransaction, processEthSignMessage, processTypedMessage, + processTypedMessageV3, processPersonalMessage, }), createPendingNonceMiddleware({ getPendingNonce }), diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index c1667d9a6..c21e9c764 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -11,6 +11,8 @@ const createInfuraClient = require('./createInfuraClient') const createJsonRpcClient = require('./createJsonRpcClient') const createLocalhostClient = require('./createLocalhostClient') const { createSwappableProxy, createEventEmitterProxy } = require('swappable-obj-proxy') +const extend = require('extend') +const networks = { networkList: {} } const { ROPSTEN, @@ -29,6 +31,10 @@ const defaultProviderConfig = { type: testMode ? RINKEBY : MAINNET, } +const defaultNetworkConfig = { + ticker: 'ETH', +} + module.exports = class NetworkController extends EventEmitter { constructor (opts = {}) { @@ -39,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 }) this.on('networkDidChange', this.lookupNetwork) // provider and block tracker this._provider = null @@ -51,8 +58,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() } @@ -72,7 +79,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) } @@ -85,18 +105,32 @@ module.exports = class NetworkController extends EventEmitter { if (!this._provider) { return log.warn('NetworkController - lookupNetwork aborted due to missing provider') } + var { type } = this.providerStore.getState() 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) + // first attempt to perform lookup via eth_chainId + ethQuery.sendAsync({ method: 'eth_chainId' }, (err, chainIdHex) => { + if (err) { + // if eth_chainId is not supported, fallback to net_verion + ethQuery.sendAsync({ method: 'net_version' }, (err, network) => { + if (err) return this.setNetworkState('loading') + log.info(`net_version returned ${network}`) + this.setNetworkState(network, type) + }) + return + } + const chainId = Number.parseInt(chainIdHex, 16) + log.info(`net_version returned ${chainId}`) + this.setNetworkState(chainId, type) }) } - setRpcTarget (rpcTarget) { + setRpcTarget (rpcTarget, chainId, ticker = 'ETH', nickname = '') { const providerConfig = { type: 'rpc', rpcTarget, + chainId, + ticker, + nickname, } this.providerConfig = providerConfig } @@ -132,7 +166,7 @@ module.exports = class NetworkController extends EventEmitter { } _configureProvider (opts) { - const { type, rpcTarget } = opts + const { type, rpcTarget, chainId, ticker, nickname } = opts // infura type-based endpoints const isInfura = INFURA_PROVIDER_TYPES.includes(type) if (isInfura) { @@ -142,7 +176,7 @@ module.exports = class NetworkController extends EventEmitter { 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}"`) } @@ -152,6 +186,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) } _configureLocalhostProvider () { @@ -160,9 +199,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) } diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 689506a7a..eaeaee499 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -25,7 +25,7 @@ class PreferencesController { */ constructor (opts = {}) { const initState = extend({ - frequentRpcList: [], + frequentRpcListDetail: [], currentAccountTab: 'history', accountTokens: {}, assetImages: {}, @@ -39,7 +39,7 @@ class PreferencesController { seedWords: null, forgottenPassword: false, preferences: { - useETHAsPrimaryCurrency: true, + useNativeCurrencyAsPrimaryCurrency: true, }, }, opts.initState) @@ -104,7 +104,7 @@ class PreferencesController { * @param {Function} - end */ async requestWatchAsset (req, res, next, end) { - if (req.method === 'metamask_watchAsset') { + if (req.method === 'metamask_watchAsset' || req.method === 'wallet_watchAsset') { const { type, options } = req.params switch (type) { case 'ERC20': @@ -392,19 +392,22 @@ class PreferencesController { * Adds custom RPC url to state. * * @param {string} url The RPC url to add to frequentRpcList. + * @param {number} chainId Optional chainId of the selected network. + * @param {string} ticker Optional ticker symbol of the selected network. + * @param {string} nickname Optional nickname of the selected network. * @returns {Promise<array>} Promise resolving to updated frequentRpcList. * */ - addToFrequentRpcList (url) { - const rpcList = this.getFrequentRpcList() - const index = rpcList.findIndex((element) => { return element === url }) + addToFrequentRpcList (url, chainId, ticker = 'ETH', nickname = '') { + const rpcList = this.getFrequentRpcListDetail() + const index = rpcList.findIndex((element) => { return element.rpcUrl === url }) if (index !== -1) { rpcList.splice(index, 1) } if (url !== 'http://localhost:8545') { - rpcList.push(url) + rpcList.push({ rpcUrl: url, chainId, ticker, nickname }) } - this.store.updateState({ frequentRpcList: rpcList }) + this.store.updateState({ frequentRpcListDetail: rpcList }) return Promise.resolve(rpcList) } @@ -416,23 +419,23 @@ class PreferencesController { * */ removeFromFrequentRpcList (url) { - const rpcList = this.getFrequentRpcList() - const index = rpcList.findIndex((element) => { return element === url }) + const rpcList = this.getFrequentRpcListDetail() + const index = rpcList.findIndex((element) => { return element.rpcUrl === url }) if (index !== -1) { rpcList.splice(index, 1) } - this.store.updateState({ frequentRpcList: rpcList }) + this.store.updateState({ frequentRpcListDetail: rpcList }) return Promise.resolve(rpcList) } /** - * Getter for the `frequentRpcList` property. + * Getter for the `frequentRpcListDetail` property. * - * @returns {array<string>} An array of one or two rpc urls. + * @returns {array<array>} An array of rpc urls. * */ - getFrequentRpcList () { - return this.store.getState().frequentRpcList + getFrequentRpcListDetail () { + return this.store.getState().frequentRpcListDetail } /** diff --git a/app/scripts/lib/contracts/registrar.js b/app/scripts/lib/ens-ipfs/contracts/registrar.js index 99ca24458..99ca24458 100644 --- a/app/scripts/lib/contracts/registrar.js +++ b/app/scripts/lib/ens-ipfs/contracts/registrar.js diff --git a/app/scripts/lib/contracts/resolver.js b/app/scripts/lib/ens-ipfs/contracts/resolver.js index 1bf3f90ce..1bf3f90ce 100644 --- a/app/scripts/lib/contracts/resolver.js +++ b/app/scripts/lib/ens-ipfs/contracts/resolver.js diff --git a/app/scripts/lib/ens-ipfs/resolver.js b/app/scripts/lib/ens-ipfs/resolver.js new file mode 100644 index 000000000..fe2dc1134 --- /dev/null +++ b/app/scripts/lib/ens-ipfs/resolver.js @@ -0,0 +1,54 @@ +const namehash = require('eth-ens-namehash') +const multihash = require('multihashes') +const Eth = require('ethjs-query') +const EthContract = require('ethjs-contract') +const registrarAbi = require('./contracts/registrar') +const resolverAbi = require('./contracts/resolver') + +module.exports = resolveEnsToIpfsContentId + + +async function resolveEnsToIpfsContentId ({ provider, name }) { + const eth = new Eth(provider) + const hash = namehash.hash(name) + const contract = new EthContract(eth) + // lookup registrar + const chainId = Number.parseInt(await eth.net_version(), 10) + const registrarAddress = getRegistrarForChainId(chainId) + if (!registrarAddress) { + throw new Error(`EnsIpfsResolver - no known ens-ipfs registrar for chainId "${chainId}"`) + } + const Registrar = contract(registrarAbi).at(registrarAddress) + // lookup resolver + const resolverLookupResult = await Registrar.resolver(hash) + const resolverAddress = resolverLookupResult[0] + if (hexValueIsEmpty(resolverAddress)) { + throw new Error(`EnsIpfsResolver - no resolver found for name "${name}"`) + } + const Resolver = contract(resolverAbi).at(resolverAddress) + // lookup content id + const contentLookupResult = await Resolver.content(hash) + const contentHash = contentLookupResult[0] + if (hexValueIsEmpty(contentHash)) { + throw new Error(`EnsIpfsResolver - no content ID found for name "${name}"`) + } + const nonPrefixedHex = contentHash.slice(2) + const buffer = multihash.fromHexString(nonPrefixedHex) + const contentId = multihash.toB58String(multihash.encode(buffer, 'sha2-256')) + return contentId +} + +function hexValueIsEmpty(value) { + return [undefined, null, '0x', '0x0', '0x0000000000000000000000000000000000000000000000000000000000000000'].includes(value) +} + +function getRegistrarForChainId (chainId) { + switch (chainId) { + // mainnet + case 1: + return '0x314159265dd8dbb310642f98f50c066173c1259b' + // ropsten + case 3: + return '0x112234455c3a32fd11230c42e7bccd4a84e02010' + } +} diff --git a/app/scripts/lib/ens-ipfs/setup.js b/app/scripts/lib/ens-ipfs/setup.js new file mode 100644 index 000000000..45eb1ce14 --- /dev/null +++ b/app/scripts/lib/ens-ipfs/setup.js @@ -0,0 +1,63 @@ +const urlUtil = require('url') +const extension = require('extensionizer') +const resolveEnsToIpfsContentId = require('./resolver.js') + +const supportedTopLevelDomains = ['eth'] + +module.exports = setupEnsIpfsResolver + +function setupEnsIpfsResolver({ provider }) { + + // install listener + const urlPatterns = supportedTopLevelDomains.map(tld => `*://*.${tld}/*`) + extension.webRequest.onErrorOccurred.addListener(webRequestDidFail, { urls: urlPatterns }) + + // return api object + return { + // uninstall listener + remove () { + extension.webRequest.onErrorOccurred.removeListener(webRequestDidFail) + }, + } + + async function webRequestDidFail (details) { + const { tabId, url } = details + // ignore requests that are not associated with tabs + if (tabId === -1) return + // parse ens name + const urlData = urlUtil.parse(url) + const { hostname: name, path, search } = urlData + const domainParts = name.split('.') + const topLevelDomain = domainParts[domainParts.length - 1] + // if unsupported TLD, abort + if (!supportedTopLevelDomains.includes(topLevelDomain)) return + // otherwise attempt resolve + attemptResolve({ tabId, name, path, search }) + } + + async function attemptResolve({ tabId, name, path, search }) { + extension.tabs.update(tabId, { url: `loading.html` }) + try { + const ipfsContentId = await resolveEnsToIpfsContentId({ provider, name }) + let url = `https://gateway.ipfs.io/ipfs/${ipfsContentId}${path}${search || ''}` + try { + // check if ipfs gateway has result + const response = await fetch(url, { method: 'HEAD' }) + // if failure, redirect to 404 page + if (response.status !== 200) { + extension.tabs.update(tabId, { url: '404.html' }) + return + } + // otherwise redirect to the correct page + extension.tabs.update(tabId, { url }) + } catch (err) { + console.warn(err) + // if HEAD fetch failed, redirect so user can see relevant error page + extension.tabs.update(tabId, { url }) + } + } catch (err) { + console.warn(err) + extension.tabs.update(tabId, { url: `error.html?name=${name}` }) + } + } +} diff --git a/app/scripts/lib/ipfsContent.js b/app/scripts/lib/ipfsContent.js deleted file mode 100644 index 8b08453c4..000000000 --- a/app/scripts/lib/ipfsContent.js +++ /dev/null @@ -1,46 +0,0 @@ -const extension = require('extensionizer') -const resolver = require('./resolver.js') - -module.exports = function (provider) { - function ipfsContent (details) { - const name = details.url.substring(7, details.url.length - 1) - let clearTime = null - if (/^.+\.eth$/.test(name) === false) return - - extension.tabs.query({active: true}, tab => { - extension.tabs.update(tab.id, { url: 'loading.html' }) - - clearTime = setTimeout(() => { - return extension.tabs.update(tab.id, { url: '404.html' }) - }, 60000) - - resolver.resolve(name, provider).then(ipfsHash => { - clearTimeout(clearTime) - let url = 'https://ipfs.infura.io/ipfs/' + ipfsHash - return fetch(url, { method: 'HEAD' }).then(response => response.status).then(statusCode => { - if (statusCode !== 200) return extension.tabs.update(tab.id, { url: '404.html' }) - extension.tabs.update(tab.id, { url: url }) - }) - .catch(err => { - url = 'https://ipfs.infura.io/ipfs/' + ipfsHash - extension.tabs.update(tab.id, {url: url}) - return err - }) - }) - .catch(err => { - clearTimeout(clearTime) - const url = err === 'unsupport' ? 'unsupport' : 'error' - extension.tabs.update(tab.id, {url: `${url}.html?name=${name}`}) - }) - }) - return { cancel: true } - } - - extension.webRequest.onErrorOccurred.addListener(ipfsContent, {urls: ['*://*.eth/'], types: ['main_frame']}) - - return { - remove () { - extension.webRequest.onErrorOccurred.removeListener(ipfsContent) - }, - } -} diff --git a/app/scripts/lib/resolver.js b/app/scripts/lib/resolver.js deleted file mode 100644 index ff0fed161..000000000 --- a/app/scripts/lib/resolver.js +++ /dev/null @@ -1,71 +0,0 @@ -const namehash = require('eth-ens-namehash') -const multihash = require('multihashes') -const HttpProvider = require('ethjs-provider-http') -const Eth = require('ethjs-query') -const EthContract = require('ethjs-contract') -const registrarAbi = require('./contracts/registrar') -const resolverAbi = require('./contracts/resolver') - -function ens (name, provider) { - const eth = new Eth(new HttpProvider(getProvider(provider.type))) - const hash = namehash.hash(name) - const contract = new EthContract(eth) - const Registrar = contract(registrarAbi).at(getRegistrar(provider.type)) - return new Promise((resolve, reject) => { - if (provider.type === 'mainnet' || provider.type === 'ropsten') { - Registrar.resolver(hash).then((address) => { - if (address === '0x0000000000000000000000000000000000000000') { - reject(null) - } else { - const Resolver = contract(resolverAbi).at(address['0']) - return Resolver.content(hash) - } - }).then((contentHash) => { - if (contentHash['0'] === '0x0000000000000000000000000000000000000000000000000000000000000000') reject(null) - if (contentHash.ret !== '0x') { - const hex = contentHash['0'].substring(2) - const buf = multihash.fromHexString(hex) - resolve(multihash.toB58String(multihash.encode(buf, 'sha2-256'))) - } else { - reject(null) - } - }) - } else { - return reject('unsupport') - } - }) -} - -function getProvider (type) { - switch (type) { - case 'mainnet': - return 'https://mainnet.infura.io/' - case 'ropsten': - return 'https://ropsten.infura.io/' - default: - return 'http://localhost:8545/' - } -} - -function getRegistrar (type) { - switch (type) { - case 'mainnet': - return '0x314159265dd8dbb310642f98f50c066173c1259b' - case 'ropsten': - return '0x112234455c3a32fd11230c42e7bccd4a84e02010' - default: - return '0x0000000000000000000000000000000000000000' - } -} - -module.exports.resolve = function (name, provider) { - const path = name.split('.') - const topLevelDomain = path[path.length - 1] - if (topLevelDomain === 'eth' || topLevelDomain === 'test') { - return ens(name, provider) - } else { - return new Promise((resolve, reject) => { - reject(null) - }) - } -} diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 7913662d4..1f6a8659b 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -138,12 +138,12 @@ module.exports = class MetamaskController extends EventEmitter { this.accountTracker.stop() } }) - + // ensure accountTracker updates balances after network change this.networkController.on('networkDidChange', () => { this.accountTracker._updateAccounts() }) - + // key mgmt const additionalKeyrings = [TrezorKeyring, LedgerBridgeKeyring] this.keyringController = new KeyringController({ @@ -197,6 +197,8 @@ module.exports = class MetamaskController extends EventEmitter { }) this.networkController.on('networkDidChange', () => { this.balancesController.updateAllBalances() + var currentCurrency = this.currencyController.getCurrentCurrency() + this.setCurrentCurrency(currentCurrency, function() {}) }) this.balancesController.updateAllBalances() @@ -275,6 +277,8 @@ module.exports = class MetamaskController extends EventEmitter { processTransaction: this.newUnapprovedTransaction.bind(this), // msg signing processEthSignMessage: this.newUnsignedMessage.bind(this), + processTypedMessage: this.newUnsignedTypedMessage.bind(this), + processTypedMessageV3: this.newUnsignedTypedMessage.bind(this), processPersonalMessage: this.newUnsignedPersonalMessage.bind(this), getPendingNonce: this.getPendingNonce.bind(this), } @@ -978,8 +982,8 @@ module.exports = class MetamaskController extends EventEmitter { * @param {Object} msgParams - The params passed to eth_signTypedData. * @param {Function} cb - The callback function, called with the signature. */ - newUnsignedTypedMessage (msgParams, req) { - const promise = this.typedMessageManager.addUnapprovedMessageAsync(msgParams, req) + newUnsignedTypedMessage (msgParams, req, version) { + const promise = this.typedMessageManager.addUnapprovedMessageAsync(msgParams, req, version) this.sendUpdate() this.opts.showUnconfirmedMessage() return promise @@ -1273,10 +1277,6 @@ module.exports = class MetamaskController extends EventEmitter { engine.push(subscriptionManager.middleware) // watch asset engine.push(this.preferencesController.requestWatchAsset.bind(this.preferencesController)) - // sign typed data middleware - engine.push(this.createTypedDataMiddleware('eth_signTypedData', 'V1').bind(this)) - engine.push(this.createTypedDataMiddleware('eth_signTypedData_v1', 'V1').bind(this)) - engine.push(this.createTypedDataMiddleware('eth_signTypedData_v3', 'V3', true).bind(this)) // forward to metamask primary provider engine.push(createProviderMiddleware({ provider })) @@ -1412,10 +1412,13 @@ module.exports = class MetamaskController extends EventEmitter { * @param {Function} cb - A callback function returning currency info. */ setCurrentCurrency (currencyCode, cb) { + const { ticker } = this.networkController.getNetworkConfig() try { + this.currencyController.setNativeCurrency(ticker) this.currencyController.setCurrentCurrency(currencyCode) this.currencyController.updateConversionRate() const data = { + nativeCurrency: ticker || 'ETH', conversionRate: this.currencyController.getConversionRate(), currentCurrency: this.currencyController.getCurrentCurrency(), conversionDate: this.currencyController.getConversionDate(), @@ -1454,11 +1457,14 @@ module.exports = class MetamaskController extends EventEmitter { /** * A method for selecting a custom URL for an ethereum RPC provider. * @param {string} rpcTarget - A URL for a valid Ethereum RPC API. + * @param {number} chainId - The chainId of the selected network. + * @param {string} ticker - The ticker symbol of the selected network. + * @param {string} nickname - Optional nickname of the selected network. * @returns {Promise<String>} - The RPC Target URL confirmed. */ - async setCustomRpc (rpcTarget) { - this.networkController.setRpcTarget(rpcTarget) - await this.preferencesController.addToFrequentRpcList(rpcTarget) + async setCustomRpc (rpcTarget, chainId, ticker = 'ETH', nickname = '') { + this.networkController.setRpcTarget(rpcTarget, chainId, ticker, nickname) + await this.preferencesController.addToFrequentRpcList(rpcTarget, chainId, ticker, nickname) return rpcTarget } @@ -1542,27 +1548,6 @@ module.exports = class MetamaskController extends EventEmitter { * @param {Function} - next * @param {Function} - end */ - createTypedDataMiddleware (methodName, version, reverse) { - return async (req, res, next, end) => { - const { method, params } = req - if (method === methodName) { - const promise = this.typedMessageManager.addUnapprovedMessageAsync({ - data: reverse ? params[1] : params[0], - from: reverse ? params[0] : params[1], - }, req, version) - this.sendUpdate() - this.opts.showUnconfirmedMessage() - try { - res.result = await promise - end() - } catch (error) { - end(error) - } - } else { - next() - } - } - } /** * Adds a domain to the {@link BlacklistController} whitelist |