diff --git a/.gitattributes b/.gitattributes index 34ffa305d..bcc9d38ef 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,8 @@ * text=auto CHANGELOG.md merge=union +.metamaskrc.dist linguist-language=ini + # Reviewing the lockfile contents is an important step in verifying that # we're using the dependencies we expect to be using package-lock.json linguist-generated=false diff --git a/.metamaskrc.dist b/.metamaskrc.dist new file mode 100644 index 000000000..a4c065503 --- /dev/null +++ b/.metamaskrc.dist @@ -0,0 +1,2 @@ +; Extra environment variables +INFURA_PROJECT_ID=00000000000 diff --git a/README.md b/README.md index 09f8d2857..30550286c 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ To learn how to contribute to the MetaMask project itself, visit our [Internal D - If you are using [nvm](https://github.com/creationix/nvm#installation) (recommended) running `nvm use` will automatically choose the right node version for you. - Install [Yarn](https://yarnpkg.com/en/docs/install) - Install dependencies: `yarn` +- Copy the `.metamaskrc.dist` file to `.metamaskrc` - Build the project to the `./dist/` folder with `yarn dist`. - Optionally, to start a development build (e.g. with logging and file watching) run `yarn start` instead. - To start the [React DevTools](https://github.com/facebook/react-devtools) and [Redux DevTools Extension](http://extension.remotedev.io) diff --git a/app/scripts/background.js b/app/scripts/background.js index 3df32dfeb..2834d0c6a 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -227,6 +227,7 @@ function setupController (initState, initLangCode) { // const controller = new MetamaskController({ + infuraProjectId: process.env.INFURA_PROJECT_ID, // User confirmation callbacks: showUnconfirmedMessage: triggerUi, showUnapprovedTx: triggerUi, diff --git a/app/scripts/controllers/network/createInfuraClient.js b/app/scripts/controllers/network/createInfuraClient.js index c961aeca1..66aa69472 100644 --- a/app/scripts/controllers/network/createInfuraClient.js +++ b/app/scripts/controllers/network/createInfuraClient.js @@ -10,8 +10,13 @@ import createInfuraMiddleware from 'eth-json-rpc-infura' import BlockTracker from 'eth-block-tracker' import * as networkEnums from './enums' -export default function createInfuraClient ({ network }) { - const infuraMiddleware = createInfuraMiddleware({ network, maxAttempts: 5, source: 'metamask' }) +export default function createInfuraClient ({ network, projectId }) { + const infuraMiddleware = createInfuraMiddleware({ + network, + projectId, + maxAttempts: 5, + source: 'metamask', + }) const infuraProvider = providerFromMiddleware(infuraMiddleware) const blockTracker = new BlockTracker({ provider: infuraProvider }) diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index 29e878cc8..1b4caeb6d 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -62,6 +62,21 @@ export default class NetworkController extends EventEmitter { this._blockTrackerProxy = null } + /** + * Sets the Infura project ID + * + * @param {string} projectId - The Infura project ID + * @throws {Error} if the project ID is not a valid string + * @return {void} + */ + setInfuraProjectId (projectId) { + if (!projectId || typeof projectId !== 'string') { + throw new Error('Invalid Infura project ID') + } + + this._infuraProjectId = projectId + } + initializeProvider (providerParams) { this._baseProviderParams = providerParams const { type, rpcTarget, chainId, ticker, nickname } = this.providerStore.getState() @@ -177,7 +192,7 @@ export default class NetworkController extends EventEmitter { // infura type-based endpoints const isInfura = INFURA_PROVIDER_TYPES.includes(type) if (isInfura) { - this._configureInfuraProvider(opts) + this._configureInfuraProvider(type, this._infuraProjectId) // other type-based rpc endpoints } else if (type === LOCALHOST) { this._configureLocalhostProvider() @@ -189,10 +204,11 @@ export default class NetworkController extends EventEmitter { } } - _configureInfuraProvider ({ type }) { + _configureInfuraProvider (type, projectId) { log.info('NetworkController - configureInfuraProvider', type) const networkClient = createInfuraClient({ network: type, + projectId, }) this._setNetworkClient(networkClient) // setup networkConfig diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index f19e12bed..8d1c462a5 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -97,6 +97,7 @@ export default class MetamaskController extends EventEmitter { // controller initialization order matters this.networkController = new NetworkController(initState.NetworkController) + this.networkController.setInfuraProjectId(opts.infuraProjectId) this.preferencesController = new PreferencesController({ initState: initState.PreferencesController, diff --git a/development/build/scripts.js b/development/build/scripts.js index c6e3e4173..bdeb1e6ab 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -15,7 +15,9 @@ const pify = require('pify') const endOfStream = pify(require('end-of-stream')) const { makeStringTransform } = require('browserify-transform-tools') -const conf = require('rc')('metamask', {}) +const conf = require('rc')('metamask', { + INFURA_PROJECT_ID: process.env.INFURA_PROJECT_ID, +}) const packageJSON = require('../../package.json') const { createTask, composeParallel, composeSeries, runInChildProcess } = require('./task') @@ -326,6 +328,11 @@ function createScriptTasks ({ browserPlatforms, livereload }) { ETH_GAS_STATION_API_KEY: process.env.ETH_GAS_STATION_API_KEY || '', CONF: opts.devMode ? conf : ({}), SENTRY_DSN: process.env.SENTRY_DSN, + INFURA_PROJECT_ID: conf.INFURA_PROJECT_ID || ( + opts.testing + ? '00000000000000000000000000000000' + : undefined + ), }), { global: true, }) diff --git a/package.json b/package.json index 6c81c900b..d429a3c11 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "eth-ens-namehash": "^2.0.8", "eth-json-rpc-errors": "^2.0.2", "eth-json-rpc-filters": "^4.1.1", - "eth-json-rpc-infura": "^4.0.2", + "eth-json-rpc-infura": "^5.0.0", "eth-json-rpc-middleware": "^5.0.2", "eth-keyring-controller": "^6.1.0", "eth-method-registry": "^1.2.0", diff --git a/test/unit/app/controllers/detect-tokens-test.js b/test/unit/app/controllers/detect-tokens-test.js index 0b65e9258..6798703c1 100644 --- a/test/unit/app/controllers/detect-tokens-test.js +++ b/test/unit/app/controllers/detect-tokens-test.js @@ -1,5 +1,4 @@ import assert from 'assert' -import nock from 'nock' import sinon from 'sinon' import ObservableStore from 'obs-store' import contracts from 'eth-contract-metadata' @@ -21,13 +20,9 @@ describe('DetectTokensController', function () { } beforeEach(async function () { - - nock('https://api.infura.io') - .get(/.*/u) - .reply(200) - keyringMemStore = new ObservableStore({ isUnlocked: false }) network = new NetworkController() + network.setInfuraProjectId('foo') preferences = new PreferencesController({ network }) preferences.setAddresses([ '0x7e57e2', @@ -39,7 +34,6 @@ describe('DetectTokensController', function () { after(function () { sandbox.restore() - nock.cleanAll() }) it('should poll on correct interval', async function () { diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js index e15f2880b..35c695894 100644 --- a/test/unit/app/controllers/metamask-controller-test.js +++ b/test/unit/app/controllers/metamask-controller-test.js @@ -82,19 +82,6 @@ describe('MetaMaskController', function () { beforeEach(function () { - nock('https://api.infura.io') - .get('/v1/ticker/ethusd') - .reply(200, '{"base": "ETH", "quote": "USD", "bid": 288.45, "ask": 288.46, "volume": 112888.17569277, "exchange": "bitfinex", "total_volume": 272175.00106721005, "num_exchanges": 8, "timestamp": 1506444677}') - - nock('https://api.infura.io') - .get('/v1/ticker/ethjpy') - .reply(200, '{"base": "ETH", "quote": "JPY", "bid": 32300.0, "ask": 32400.0, "volume": 247.4616071, "exchange": "kraken", "total_volume": 247.4616071, "num_exchanges": 1, "timestamp": 1506444676}') - - nock('https://api.infura.io') - .persist() - .get(/.*/u) - .reply(200) - nock('https://min-api.cryptocompare.com') .persist() .get(/.*/u) @@ -114,6 +101,7 @@ describe('MetaMaskController', function () { }, initState: cloneDeep(firstTimeState), platform: { showTransactionNotification: () => undefined, getVersion: () => 'foo' }, + infuraProjectId: 'foo', }) // add sinon method spies diff --git a/test/unit/app/controllers/network/network-controller-test.js b/test/unit/app/controllers/network/network-controller-test.js index 161df6170..882c7ac54 100644 --- a/test/unit/app/controllers/network/network-controller-test.js +++ b/test/unit/app/controllers/network/network-controller-test.js @@ -1,5 +1,4 @@ import assert from 'assert' -import nock from 'nock' import NetworkController from '../../../../../app/scripts/controllers/network' import { getNetworkDisplayName } from '../../../../../app/scripts/controllers/network/util' @@ -12,16 +11,8 @@ describe('NetworkController', function () { } beforeEach(function () { - nock('https://rinkeby.infura.io') - .persist() - .post('/metamask') - .reply(200) - networkController = new NetworkController() - }) - - afterEach(function () { - nock.cleanAll() + networkController.setInfuraProjectId('foo') }) describe('#provider', function () { diff --git a/test/unit/ui/app/actions.spec.js b/test/unit/ui/app/actions.spec.js index 770608bdc..2dc949c84 100644 --- a/test/unit/ui/app/actions.spec.js +++ b/test/unit/ui/app/actions.spec.js @@ -47,6 +47,7 @@ describe('Actions', function () { }, }, initState: cloneDeep(firstTimeState), + infuraProjectId: 'foo', }) metamaskController.threeBoxController = { diff --git a/ui/app/pages/settings/networks-tab/networks-tab.constants.js b/ui/app/pages/settings/networks-tab/networks-tab.constants.js index 453a616b2..01e0666ed 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.constants.js +++ b/ui/app/pages/settings/networks-tab/networks-tab.constants.js @@ -3,7 +3,7 @@ const defaultNetworksData = [ labelKey: 'mainnet', iconColor: '#29B6AF', providerType: 'mainnet', - rpcUrl: 'https://api.infura.io/v1/jsonrpc/mainnet', + rpcUrl: `https://mainnet.infura.io/v3/${process.env.INFURA_PROJECT_ID}`, chainId: '1', ticker: 'ETH', blockExplorerUrl: 'https://etherscan.io', @@ -12,7 +12,7 @@ const defaultNetworksData = [ labelKey: 'ropsten', iconColor: '#FF4A8D', providerType: 'ropsten', - rpcUrl: 'https://api.infura.io/v1/jsonrpc/ropsten', + rpcUrl: `https://ropsten.infura.io/v3/${process.env.INFURA_PROJECT_ID}`, chainId: '3', ticker: 'ETH', blockExplorerUrl: 'https://ropsten.etherscan.io', @@ -21,7 +21,7 @@ const defaultNetworksData = [ labelKey: 'rinkeby', iconColor: '#F6C343', providerType: 'rinkeby', - rpcUrl: 'https://api.infura.io/v1/jsonrpc/rinkeby', + rpcUrl: `https://rinkeby.infura.io/v3/${process.env.INFURA_PROJECT_ID}`, chainId: '4', ticker: 'ETH', blockExplorerUrl: 'https://rinkeby.etherscan.io', @@ -30,7 +30,7 @@ const defaultNetworksData = [ labelKey: 'goerli', iconColor: '#3099f2', providerType: 'goerli', - rpcUrl: 'https://api.infura.io/v1/jsonrpc/goerli', + rpcUrl: `https://goerli.infura.io/v3/${process.env.INFURA_PROJECT_ID}`, chainId: '5', ticker: 'ETH', blockExplorerUrl: 'https://goerli.etherscan.io', @@ -39,7 +39,7 @@ const defaultNetworksData = [ labelKey: 'kovan', iconColor: '#9064FF', providerType: 'kovan', - rpcUrl: 'https://api.infura.io/v1/jsonrpc/kovan', + rpcUrl: `https://kovan.infura.io/v3/${process.env.INFURA_PROJECT_ID}`, chainId: '42', ticker: 'ETH', blockExplorerUrl: 'https://etherscan.io', diff --git a/yarn.lock b/yarn.lock index 479e1f858..e6a7b4d5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10371,7 +10371,7 @@ eth-json-rpc-infura@^3.1.0: json-rpc-error "^2.0.0" tape "^4.8.0" -eth-json-rpc-infura@^4.0.1, eth-json-rpc-infura@^4.0.2: +eth-json-rpc-infura@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-4.0.2.tgz#8af1a1a2e9a0a82aaa302bbc96fb1a4c15d69b83" integrity sha512-dvgOrci9lZqpjpp0hoC3Zfedhg3aIpLFVDH0TdlKxRlkhR75hTrKTwxghDrQwE0bn3eKrC8RsN1m/JdnIWltpw== @@ -10381,6 +10381,16 @@ eth-json-rpc-infura@^4.0.1, eth-json-rpc-infura@^4.0.2: eth-json-rpc-middleware "^4.1.4" json-rpc-engine "^5.1.3" +eth-json-rpc-infura@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-5.0.0.tgz#a666efe860659ffa09e918abdf9aab9f2434e508" + integrity sha512-TvRgnDHsxNblUpFo1KTqsgfeZ0rMEg6Ga+v+Zbqjb467txODg6oPamKJKh/odOs+MXtYpt9e7d4yJCy+5azq5w== + dependencies: + eth-json-rpc-middleware "^4.4.0" + eth-rpc-errors "^3.0.0" + json-rpc-engine "^5.1.3" + node-fetch "^2.6.0" + eth-json-rpc-middleware@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz#5c9d4c28f745ccb01630f0300ba945f4bef9593f" @@ -10400,7 +10410,7 @@ eth-json-rpc-middleware@^1.5.0: promise-to-callback "^1.0.0" tape "^4.6.3" -eth-json-rpc-middleware@^4.1.4, eth-json-rpc-middleware@^4.1.5: +eth-json-rpc-middleware@^4.1.4, eth-json-rpc-middleware@^4.1.5, eth-json-rpc-middleware@^4.4.0: version "4.4.1" resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-4.4.1.tgz#07d3dd0724c24a8d31e4a172ee96271da71b4228" integrity sha512-yoSuRgEYYGFdVeZg3poWOwAlRI+MoBIltmOB86MtpoZjvLbou9EB/qWMOWSmH2ryCWLW97VYY6NWsmWm3OAA7A== @@ -10528,6 +10538,13 @@ eth-rpc-errors@^2.1.1: dependencies: fast-safe-stringify "^2.0.6" +eth-rpc-errors@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eth-rpc-errors/-/eth-rpc-errors-3.0.0.tgz#d7b22653c70dbf9defd4ef490fd08fe70608ca10" + integrity sha512-iPPNHPrLwUlR9xCSYm7HHQjWBasor3+KZfRvwEWxMz3ca0yqnlBeJrnyphkGIXZ4J7AMAaOLmwy4AWhnxOiLxg== + dependencies: + fast-safe-stringify "^2.0.6" + eth-sig-util@2.3.0, eth-sig-util@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-2.3.0.tgz#c54a6ac8e8796f7e25f59cf436982a930e645231"