diff --git a/app/scripts/controllers/incoming-transactions.js b/app/scripts/controllers/incoming-transactions.js index 94a4b6c86..6e50b6774 100644 --- a/app/scripts/controllers/incoming-transactions.js +++ b/app/scripts/controllers/incoming-transactions.js @@ -6,12 +6,18 @@ import { bnToHex } from '../lib/util' import fetchWithTimeout from '../lib/fetch-with-timeout' import { - ROPSTEN, - RINKEBY, - KOVAN, + CHAIN_ID_TO_NETWORK_ID_MAP, + CHAIN_ID_TO_TYPE_MAP, GOERLI, + GOERLI_CHAIN_ID, + KOVAN, + KOVAN_CHAIN_ID, MAINNET, - NETWORK_TYPE_TO_ID_MAP, + MAINNET_CHAIN_ID, + RINKEBY, + RINKEBY_CHAIN_ID, + ROPSTEN, + ROPSTEN_CHAIN_ID, } from './network/enums' const fetch = fetchWithTimeout({ @@ -25,6 +31,14 @@ const fetch = fetchWithTimeout({ * Note that only the built-in Infura networks are supported (i.e. anything in `INFURA_PROVIDER_TYPES`). We will not * attempt to retrieve incoming transactions on any custom RPC endpoints. */ +const etherscanSupportedNetworks = [ + GOERLI_CHAIN_ID, + KOVAN_CHAIN_ID, + MAINNET_CHAIN_ID, + RINKEBY_CHAIN_ID, + ROPSTEN_CHAIN_ID, +] + export default class IncomingTransactionsController { constructor (opts = {}) { @@ -36,7 +50,6 @@ export default class IncomingTransactionsController { this.blockTracker = blockTracker this.networkController = networkController this.preferencesController = preferencesController - this.getCurrentNetwork = () => networkController.getProviderConfig().type this._onLatestBlock = async (newBlockNumberHex) => { const selectedAddress = this.preferencesController.getSelectedAddress() @@ -50,11 +63,11 @@ export default class IncomingTransactionsController { const initState = { incomingTransactions: {}, incomingTxLastFetchedBlocksByNetwork: { - [ROPSTEN]: null, - [RINKEBY]: null, - [KOVAN]: null, [GOERLI]: null, + [KOVAN]: null, [MAINNET]: null, + [RINKEBY]: null, + [ROPSTEN]: null, }, ...opts.initState, } this.store = new ObservableStore(initState) @@ -88,11 +101,10 @@ export default class IncomingTransactionsController { }) })) - this.networkController.on('networkDidChange', async (newType) => { + this.networkController.on('networkDidChange', async () => { const address = this.preferencesController.getSelectedAddress() await this._update({ address, - networkType: newType, }) }) } @@ -113,29 +125,32 @@ export default class IncomingTransactionsController { this.blockTracker.removeListener('latest', this._onLatestBlock) } - async _update ({ address, newBlockNumberDec, networkType } = {}) { + async _update ({ address, newBlockNumberDec } = {}) { + const chainId = this.networkController.getCurrentChainId() + if (!etherscanSupportedNetworks.includes(chainId)) { + return + } try { - const dataForUpdate = await this._getDataForUpdate({ address, newBlockNumberDec, networkType }) - await this._updateStateWithNewTxData(dataForUpdate) + const dataForUpdate = await this._getDataForUpdate({ address, chainId, newBlockNumberDec }) + this._updateStateWithNewTxData(dataForUpdate) } catch (err) { log.error(err) } } - async _getDataForUpdate ({ address, newBlockNumberDec, networkType } = {}) { + async _getDataForUpdate ({ address, chainId, newBlockNumberDec } = {}) { const { incomingTransactions: currentIncomingTxs, incomingTxLastFetchedBlocksByNetwork: currentBlocksByNetwork, } = this.store.getState() - const network = networkType || this.getCurrentNetwork() - const lastFetchBlockByCurrentNetwork = currentBlocksByNetwork[network] + const lastFetchBlockByCurrentNetwork = currentBlocksByNetwork[CHAIN_ID_TO_TYPE_MAP[chainId]] let blockToFetchFrom = lastFetchBlockByCurrentNetwork || newBlockNumberDec if (blockToFetchFrom === undefined) { blockToFetchFrom = parseInt(this.blockTracker.getCurrentBlock(), 16) } - const { latestIncomingTxBlockNumber, txs: newTxs } = await this._fetchAll(address, blockToFetchFrom, network) + const { latestIncomingTxBlockNumber, txs: newTxs } = await this._fetchAll(address, blockToFetchFrom, chainId) return { latestIncomingTxBlockNumber, @@ -143,17 +158,17 @@ export default class IncomingTransactionsController { currentIncomingTxs, currentBlocksByNetwork, fetchedBlockNumber: blockToFetchFrom, - network, + chainId, } } - async _updateStateWithNewTxData ({ + _updateStateWithNewTxData ({ latestIncomingTxBlockNumber, newTxs, currentIncomingTxs, currentBlocksByNetwork, fetchedBlockNumber, - network, + chainId, }) { const newLatestBlockHashByNetwork = latestIncomingTxBlockNumber ? parseInt(latestIncomingTxBlockNumber, 10) + 1 @@ -168,28 +183,22 @@ export default class IncomingTransactionsController { this.store.updateState({ incomingTxLastFetchedBlocksByNetwork: { ...currentBlocksByNetwork, - [network]: newLatestBlockHashByNetwork, + [CHAIN_ID_TO_TYPE_MAP[chainId]]: newLatestBlockHashByNetwork, }, incomingTransactions: newIncomingTransactions, }) } - async _fetchAll (address, fromBlock, networkType) { - const fetchedTxResponse = await this._fetchTxs(address, fromBlock, networkType) + async _fetchAll (address, fromBlock, chainId) { + const fetchedTxResponse = await this._fetchTxs(address, fromBlock, chainId) return this._processTxFetchResponse(fetchedTxResponse) } - async _fetchTxs (address, fromBlock, networkType) { - let etherscanSubdomain = 'api' - const currentNetworkID = NETWORK_TYPE_TO_ID_MAP[networkType]?.networkId - - if (!currentNetworkID) { - return {} - } + async _fetchTxs (address, fromBlock, chainId) { + const etherscanSubdomain = chainId === MAINNET_CHAIN_ID + ? 'api' + : `api-${CHAIN_ID_TO_TYPE_MAP[chainId]}` - if (networkType !== MAINNET) { - etherscanSubdomain = `api-${networkType}` - } const apiUrl = `https://${etherscanSubdomain}.etherscan.io` let url = `${apiUrl}/api?module=account&action=txlist&address=${address}&tag=latest&page=1` @@ -202,17 +211,17 @@ export default class IncomingTransactionsController { return { ...parsedResponse, address, - currentNetworkID, + chainId, } } - _processTxFetchResponse ({ status, result = [], address, currentNetworkID }) { + _processTxFetchResponse ({ status, result = [], address, chainId }) { if (status === '1' && Array.isArray(result) && result.length > 0) { const remoteTxList = {} const remoteTxs = [] result.forEach((tx) => { if (!remoteTxList[tx.hash]) { - remoteTxs.push(this._normalizeTxFromEtherscan(tx, currentNetworkID)) + remoteTxs.push(this._normalizeTxFromEtherscan(tx, chainId)) remoteTxList[tx.hash] = 1 } }) @@ -241,13 +250,13 @@ export default class IncomingTransactionsController { } } - _normalizeTxFromEtherscan (txMeta, currentNetworkID) { + _normalizeTxFromEtherscan (txMeta, chainId) { const time = parseInt(txMeta.timeStamp, 10) * 1000 const status = txMeta.isError === '0' ? 'confirmed' : 'failed' return { blockNumber: txMeta.blockNumber, id: createId(), - metamaskNetworkId: currentNetworkID, + metamaskNetworkId: CHAIN_ID_TO_NETWORK_ID_MAP[chainId], status, time, txParams: { diff --git a/app/scripts/controllers/network/enums.js b/app/scripts/controllers/network/enums.js index 85adf3b45..9b0d37602 100644 --- a/app/scripts/controllers/network/enums.js +++ b/app/scripts/controllers/network/enums.js @@ -57,3 +57,21 @@ export const NETWORK_TO_NAME_MAP = { [GOERLI_CHAIN_ID]: GOERLI_DISPLAY_NAME, [MAINNET_CHAIN_ID]: MAINNET_DISPLAY_NAME, } + +export const CHAIN_ID_TO_TYPE_MAP = Object.entries(NETWORK_TYPE_TO_ID_MAP) + .reduce( + (chainIdToTypeMap, [networkType, { chainId }]) => { + chainIdToTypeMap[chainId] = networkType + return chainIdToTypeMap + }, + {}, + ) + +export const CHAIN_ID_TO_NETWORK_ID_MAP = Object.values(NETWORK_TYPE_TO_ID_MAP) + .reduce( + (chainIdToNetworkIdMap, { chainId, networkId }) => { + chainIdToNetworkIdMap[chainId] = networkId + return chainIdToNetworkIdMap + }, + {}, + ) diff --git a/test/unit/app/controllers/incoming-transactions-test.js b/test/unit/app/controllers/incoming-transactions-test.js index ccf1231ca..a227cf95f 100644 --- a/test/unit/app/controllers/incoming-transactions-test.js +++ b/test/unit/app/controllers/incoming-transactions-test.js @@ -9,15 +9,18 @@ import { GOERLI, KOVAN, MAINNET, + MAINNET_CHAIN_ID, RINKEBY, ROPSTEN, + ROPSTEN_CHAIN_ID, + ROPSTEN_NETWORK_ID, } from '../../../../app/scripts/controllers/network/enums' const IncomingTransactionsController = proxyquire('../../../../app/scripts/controllers/incoming-transactions', { '../lib/random-id': { default: () => 54321 }, }).default -const FAKE_NETWORK = 'FAKE_NETWORK' +const FAKE_CHAIN_ID = '0x1338' const MOCK_SELECTED_ADDRESS = '0x0101' function getEmptyInitState () { @@ -48,27 +51,9 @@ function getNonEmptyInitState () { } } -function getNonEmptyInitStateWithFakeNetworkState () { +function getMockNetworkController (chainId = FAKE_CHAIN_ID) { return { - incomingTransactions: { - '0x123456': { id: 777 }, - }, - incomingTxLastFetchedBlocksByNetwork: { - [ROPSTEN]: 1, - [RINKEBY]: 2, - [KOVAN]: 3, - [GOERLI]: 5, - [MAINNET]: 4, - [FAKE_NETWORK]: 1111, - }, - } -} - -function getMockNetworkController (networkType = FAKE_NETWORK) { - return { - getProviderConfig: () => { - return { type: networkType } - }, + getCurrentChainId: () => chainId, on: sinon.spy(), } } @@ -164,7 +149,6 @@ describe('IncomingTransactionsController', function () { assert.equal(incomingTransactionsController._update.callCount, 1) assert.deepEqual(incomingTransactionsController._update.getCall(0).args[0], { address: '0x0101', - networkType: 'testNetworkType', }) incomingTransactionsController._update.resetHistory() @@ -200,7 +184,7 @@ describe('IncomingTransactionsController', function () { it('should update upon latest block when started and on supported network', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(ROPSTEN), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) @@ -258,34 +242,44 @@ describe('IncomingTransactionsController', function () { ) }) - it('should update last block fetched when started and not on supported network', async function () { + it('should not update upon latest block when started and not on supported network', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), networkController: getMockNetworkController(), preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) + // reply with a valid request for any supported network, so that this test has every opportunity to fail + for (const network of [GOERLI, KOVAN, MAINNET, RINKEBY, ROPSTEN]) { + nock(`https://api${network === MAINNET ? '' : `-${network.toLowerCase()}`}.etherscan.io`) + .get(/api.+/u) + .reply( + 200, + JSON.stringify({ + status: '1', + result: [getFakeEtherscanTransaction()], + }), + ) + } const updateStateStub = sinon.stub(incomingTransactionsController.store, 'updateState') const updateStateCalled = waitUntilCalled(updateStateStub, incomingTransactionsController.store) + const putStateStub = sinon.stub(incomingTransactionsController.store, 'putState') + const putStateCalled = waitUntilCalled(putStateStub, incomingTransactionsController.store) incomingTransactionsController.start() - await updateStateCalled - - const state = incomingTransactionsController.store.getState() - assert.deepStrictEqual( - state, - { - incomingTransactions: { - ...getNonEmptyInitState().incomingTransactions, - }, - incomingTxLastFetchedBlocksByNetwork: { - ...getNonEmptyInitState().incomingTxLastFetchedBlocksByNetwork, - [FAKE_NETWORK]: 11, - }, - }, - 'Should update last block fetched', - ) + try { + await Promise.race([ + updateStateCalled, + putStateCalled, + new Promise((_, reject) => { + setTimeout(() => reject(new Error('TIMEOUT')), 1000) + }), + ]) + assert.fail('Update state should not have been called') + } catch (error) { + assert(error.message === 'TIMEOUT', 'TIMEOUT error should be thrown') + } }) it('should not update upon latest block when started and incoming transactions disabled', async function () { @@ -331,7 +325,7 @@ describe('IncomingTransactionsController', function () { it('should not update upon latest block when not started', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(ROPSTEN), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) @@ -369,7 +363,7 @@ describe('IncomingTransactionsController', function () { it('should not update upon latest block when stopped', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(ROPSTEN), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) @@ -409,7 +403,7 @@ describe('IncomingTransactionsController', function () { it('should update when the selected address changes and on supported network', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(ROPSTEN), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) @@ -473,7 +467,7 @@ describe('IncomingTransactionsController', function () { ) }) - it('should update last block fetched when selected address changes and not on supported network', async function () { + it('should not update when the selected address changes and not on supported network', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: { ...getMockBlockTracker() }, networkController: getMockNetworkController(), @@ -495,6 +489,8 @@ describe('IncomingTransactionsController', function () { } const updateStateStub = sinon.stub(incomingTransactionsController.store, 'updateState') const updateStateCalled = waitUntilCalled(updateStateStub, incomingTransactionsController.store) + const putStateStub = sinon.stub(incomingTransactionsController.store, 'putState') + const putStateCalled = waitUntilCalled(putStateStub, incomingTransactionsController.store) const subscription = incomingTransactionsController.preferencesController.store.subscribe.getCall(1).args[0] // The incoming transactions controller will always skip the first event @@ -503,28 +499,24 @@ describe('IncomingTransactionsController', function () { await subscription({ selectedAddress: MOCK_SELECTED_ADDRESS }) await subscription({ selectedAddress: NEW_MOCK_SELECTED_ADDRESS }) - await updateStateCalled - - const state = incomingTransactionsController.store.getState() - assert.deepStrictEqual( - state, - { - incomingTransactions: { - ...getNonEmptyInitState().incomingTransactions, - }, - incomingTxLastFetchedBlocksByNetwork: { - ...getNonEmptyInitState().incomingTxLastFetchedBlocksByNetwork, - [FAKE_NETWORK]: 11, - }, - }, - 'Should update last block fetched', - ) + try { + await Promise.race([ + updateStateCalled, + putStateCalled, + new Promise((_, reject) => { + setTimeout(() => reject(new Error('TIMEOUT')), 1000) + }), + ]) + assert.fail('Update state should not have been called') + } catch (error) { + assert(error.message === 'TIMEOUT', 'TIMEOUT error should be thrown') + } }) it('should update when switching to a supported network', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(ROPSTEN), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) @@ -542,7 +534,7 @@ describe('IncomingTransactionsController', function () { const updateStateCalled = waitUntilCalled(updateStateStub, incomingTransactionsController.store) const subscription = incomingTransactionsController.networkController.on.getCall(0).args[1] - incomingTransactionsController.networkController = getMockNetworkController(ROPSTEN) + incomingTransactionsController.networkController = getMockNetworkController(ROPSTEN_CHAIN_ID) await subscription(ROPSTEN) await updateStateCalled @@ -584,10 +576,11 @@ describe('IncomingTransactionsController', function () { ) }) - it('should update last block fetched when switching to an unsupported network', async function () { + it('should not update when switching to an unsupported network', async function () { + const networkController = getMockNetworkController(ROPSTEN_CHAIN_ID) const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(), + networkController, preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) @@ -605,26 +598,26 @@ describe('IncomingTransactionsController', function () { } const updateStateStub = sinon.stub(incomingTransactionsController.store, 'updateState') const updateStateCalled = waitUntilCalled(updateStateStub, incomingTransactionsController.store) + const putStateStub = sinon.stub(incomingTransactionsController.store, 'putState') + const putStateCalled = waitUntilCalled(putStateStub, incomingTransactionsController.store) const subscription = incomingTransactionsController.networkController.on.getCall(0).args[1] - await subscription('SECOND_FAKE_NETWORK') - await updateStateCalled + networkController.getCurrentChainId = () => FAKE_CHAIN_ID + await subscription() - const state = incomingTransactionsController.store.getState() - assert.deepStrictEqual( - state, - { - incomingTransactions: { - ...getNonEmptyInitState().incomingTransactions, - }, - incomingTxLastFetchedBlocksByNetwork: { - ...getNonEmptyInitState().incomingTxLastFetchedBlocksByNetwork, - SECOND_FAKE_NETWORK: 11, - }, - }, - 'Should update last block fetched', - ) + try { + await Promise.race([ + updateStateCalled, + putStateCalled, + new Promise((_, reject) => { + setTimeout(() => reject(new Error('TIMEOUT')), 1000) + }), + ]) + assert.fail('Update state should not have been called') + } catch (error) { + assert(error.message === 'TIMEOUT', 'TIMEOUT error should be thrown') + } }) }) @@ -632,66 +625,53 @@ describe('IncomingTransactionsController', function () { it('should call fetchAll with the correct params when passed a new block number and the current network has no stored block', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), - initState: getNonEmptyInitState(), + initState: getEmptyInitState(), }) incomingTransactionsController._fetchAll = sinon.stub().returns({}) - await incomingTransactionsController._getDataForUpdate({ address: 'fakeAddress', newBlockNumberDec: 999 }) - - assert(incomingTransactionsController._fetchAll.calledOnce) - - assert.deepEqual(incomingTransactionsController._fetchAll.getCall(0).args, [ - 'fakeAddress', 999, 'FAKE_NETWORK', - ]) - }) - - it('should call fetchAll with the correct params when passed a new block number but the current network has a stored block', async function () { - const incomingTransactionsController = new IncomingTransactionsController({ - blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(), - preferencesController: getMockPreferencesController(), - initState: getNonEmptyInitStateWithFakeNetworkState(), + await incomingTransactionsController._getDataForUpdate({ + address: 'fakeAddress', + chainId: ROPSTEN_CHAIN_ID, + newBlockNumberDec: 999, }) - incomingTransactionsController._fetchAll = sinon.stub().returns({}) - - await incomingTransactionsController._getDataForUpdate({ address: 'fakeAddress', newBlockNumberDec: 999 }) assert(incomingTransactionsController._fetchAll.calledOnce) assert.deepEqual(incomingTransactionsController._fetchAll.getCall(0).args, [ - 'fakeAddress', 1111, 'FAKE_NETWORK', + 'fakeAddress', 999, ROPSTEN_CHAIN_ID, ]) }) - it('should call fetchAll with the correct params when passed a new network type but no block info exists', async function () { + it('should call fetchAll with the correct params when passed a new block number but the current network has a stored block', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), - initState: getNonEmptyInitStateWithFakeNetworkState(), + initState: getNonEmptyInitState(), }) incomingTransactionsController._fetchAll = sinon.stub().returns({}) await incomingTransactionsController._getDataForUpdate({ address: 'fakeAddress', - networkType: 'NEW_FAKE_NETWORK', + chainId: ROPSTEN_CHAIN_ID, + newBlockNumberDec: 999, }) assert(incomingTransactionsController._fetchAll.calledOnce) assert.deepEqual(incomingTransactionsController._fetchAll.getCall(0).args, [ - 'fakeAddress', 10, 'NEW_FAKE_NETWORK', + 'fakeAddress', 4, ROPSTEN_CHAIN_ID, ]) }) it('should return the expected data', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), - initState: getNonEmptyInitStateWithFakeNetworkState(), + initState: getNonEmptyInitState(), }) incomingTransactionsController._fetchAll = sinon.stub().returns({ latestIncomingTxBlockNumber: 444, @@ -700,7 +680,7 @@ describe('IncomingTransactionsController', function () { const result = await incomingTransactionsController._getDataForUpdate({ address: 'fakeAddress', - networkType: 'FAKE_NETWORK', + chainId: ROPSTEN_CHAIN_ID, }) assert.deepEqual(result, { @@ -710,15 +690,14 @@ describe('IncomingTransactionsController', function () { '0x123456': { id: 777 }, }, currentBlocksByNetwork: { - [ROPSTEN]: 1, - [RINKEBY]: 2, - [KOVAN]: 3, - [GOERLI]: 5, - [MAINNET]: 4, - FAKE_NETWORK: 1111, + [GOERLI]: 1, + [KOVAN]: 2, + [MAINNET]: 3, + [RINKEBY]: 5, + [ROPSTEN]: 4, }, - fetchedBlockNumber: 1111, - network: 'FAKE_NETWORK', + fetchedBlockNumber: 4, + chainId: ROPSTEN_CHAIN_ID, }) }) }) @@ -730,15 +709,14 @@ describe('IncomingTransactionsController', function () { '0x123456': { id: 777, hash: '0x123456' }, }, currentBlocksByNetwork: { - [ROPSTEN]: 1, - [RINKEBY]: 2, - [KOVAN]: 3, - [GOERLI]: 5, - [MAINNET]: 4, - FAKE_NETWORK: 1111, + [GOERLI]: 1, + [KOVAN]: 2, + [MAINNET]: 3, + [RINKEBY]: 5, + [ROPSTEN]: 4, }, fetchedBlockNumber: 1111, - network: 'FAKE_NETWORK', + chainId: ROPSTEN_CHAIN_ID, } const MOCK_INPUT_WITH_LASTEST = { @@ -749,7 +727,7 @@ describe('IncomingTransactionsController', function () { it('should update state with correct blockhash and transactions when passed a truthy latestIncomingTxBlockNumber', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) @@ -762,7 +740,7 @@ describe('IncomingTransactionsController', function () { assert.deepEqual(incomingTransactionsController.store.updateState.getCall(0).args[0], { incomingTxLastFetchedBlocksByNetwork: { ...MOCK_INPUT_WITH_LASTEST.currentBlocksByNetwork, - 'FAKE_NETWORK': 445, + [ROPSTEN]: 445, }, incomingTransactions: { '0x123456': { id: 777, hash: '0x123456' }, @@ -774,7 +752,7 @@ describe('IncomingTransactionsController', function () { it('should update state with correct blockhash and transactions when passed a falsy latestIncomingTxBlockNumber', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) @@ -787,7 +765,7 @@ describe('IncomingTransactionsController', function () { assert.deepEqual(incomingTransactionsController.store.updateState.getCall(0).args[0], { incomingTxLastFetchedBlocksByNetwork: { ...MOCK_INPUT_WITH_LASTEST.currentBlocksByNetwork, - 'FAKE_NETWORK': 1112, + [ROPSTEN]: 1112, }, incomingTransactions: { '0x123456': { id: 777, hash: '0x123456' }, @@ -815,12 +793,12 @@ describe('IncomingTransactionsController', function () { it('should call fetch with the expected url when passed an address, block number and supported network', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) - await incomingTransactionsController._fetchTxs('0xfakeaddress', '789', ROPSTEN) + await incomingTransactionsController._fetchTxs('0xfakeaddress', '789', ROPSTEN_CHAIN_ID) assert(mockFetch.calledOnce) assert.equal(mockFetch.getCall(0).args[0], `https://api-${ROPSTEN}.etherscan.io/api?module=account&action=txlist&address=0xfakeaddress&tag=latest&page=1&startBlock=789`) @@ -829,12 +807,12 @@ describe('IncomingTransactionsController', function () { it('should call fetch with the expected url when passed an address, block number and MAINNET', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(), + networkController: getMockNetworkController(MAINNET_CHAIN_ID), preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) - await incomingTransactionsController._fetchTxs('0xfakeaddress', '789', MAINNET) + await incomingTransactionsController._fetchTxs('0xfakeaddress', '789', MAINNET_CHAIN_ID) assert(mockFetch.calledOnce) assert.equal(mockFetch.getCall(0).args[0], `https://api.etherscan.io/api?module=account&action=txlist&address=0xfakeaddress&tag=latest&page=1&startBlock=789`) @@ -843,46 +821,32 @@ describe('IncomingTransactionsController', function () { it('should call fetch with the expected url when passed an address and supported network, but a falsy block number', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) - await incomingTransactionsController._fetchTxs('0xfakeaddress', null, ROPSTEN) + await incomingTransactionsController._fetchTxs('0xfakeaddress', null, ROPSTEN_CHAIN_ID) assert(mockFetch.calledOnce) assert.equal(mockFetch.getCall(0).args[0], `https://api-${ROPSTEN}.etherscan.io/api?module=account&action=txlist&address=0xfakeaddress&tag=latest&page=1`) }) - it('should not fetch and return an empty object when passed an unsported network', async function () { - const incomingTransactionsController = new IncomingTransactionsController({ - blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(), - preferencesController: getMockPreferencesController(), - initState: getNonEmptyInitState(), - }) - - const result = await incomingTransactionsController._fetchTxs('0xfakeaddress', null, 'UNSUPPORTED_NETWORK') - - assert(mockFetch.notCalled) - assert.deepEqual(result, {}) - }) - it('should return the results from the fetch call, plus the address and currentNetworkID, when passed an address, block number and supported network', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) - const result = await incomingTransactionsController._fetchTxs('0xfakeaddress', '789', ROPSTEN) + const result = await incomingTransactionsController._fetchTxs('0xfakeaddress', '789', ROPSTEN_CHAIN_ID) assert(mockFetch.calledOnce) assert.deepEqual(result, { someKey: 'someValue', address: '0xfakeaddress', - currentNetworkID: '3', + chainId: ROPSTEN_CHAIN_ID, }) }) }) @@ -891,7 +855,7 @@ describe('IncomingTransactionsController', function () { it('should return a null block number and empty tx array if status is 0', function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) @@ -911,7 +875,7 @@ describe('IncomingTransactionsController', function () { it('should return a null block number and empty tx array if the passed result array is empty', function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) @@ -931,21 +895,21 @@ describe('IncomingTransactionsController', function () { it('should return the expected block number and tx list when passed data from a successful fetch', function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) - incomingTransactionsController._normalizeTxFromEtherscan = (tx, currentNetworkID) => ({ + incomingTransactionsController._normalizeTxFromEtherscan = (tx) => ({ ...tx, - currentNetworkID, + currentNetworkID: ROPSTEN_NETWORK_ID, normalized: true, }) const result = incomingTransactionsController._processTxFetchResponse({ status: '1', address: '0xfakeaddress', - currentNetworkID: 'FAKE_NETWORK', + chainId: ROPSTEN_CHAIN_ID, result: [ { hash: '0xabc123', @@ -1009,7 +973,7 @@ describe('IncomingTransactionsController', function () { blockNumber: 5000, time: 9, normalized: true, - currentNetworkID: 'FAKE_NETWORK', + currentNetworkID: ROPSTEN_NETWORK_ID, }, { hash: '0xabc123', @@ -1019,7 +983,7 @@ describe('IncomingTransactionsController', function () { blockNumber: 5000, time: 10, normalized: true, - currentNetworkID: 'FAKE_NETWORK', + currentNetworkID: ROPSTEN_NETWORK_ID, }, { hash: '0xabc12345', @@ -1029,7 +993,7 @@ describe('IncomingTransactionsController', function () { blockNumber: 5001, time: 11, normalized: true, - currentNetworkID: 'FAKE_NETWORK', + currentNetworkID: ROPSTEN_NETWORK_ID, }, { hash: '0xabc123456', @@ -1039,7 +1003,7 @@ describe('IncomingTransactionsController', function () { blockNumber: 5001, time: 12, normalized: true, - currentNetworkID: 'FAKE_NETWORK', + currentNetworkID: ROPSTEN_NETWORK_ID, }, ], }) @@ -1050,7 +1014,7 @@ describe('IncomingTransactionsController', function () { it('should return the expected data when the tx is in error', function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) @@ -1066,12 +1030,12 @@ describe('IncomingTransactionsController', function () { to: '0xe', value: '15', hash: '0xg', - }, 'FAKE_NETWORK') + }, ROPSTEN_CHAIN_ID) assert.deepEqual(result, { blockNumber: 333, id: 54321, - metamaskNetworkId: 'FAKE_NETWORK', + metamaskNetworkId: ROPSTEN_NETWORK_ID, status: 'failed', time: 4444000, txParams: { @@ -1090,7 +1054,7 @@ describe('IncomingTransactionsController', function () { it('should return the expected data when the tx is not in error', function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: getMockBlockTracker(), - networkController: getMockNetworkController(), + networkController: getMockNetworkController(ROPSTEN_CHAIN_ID), preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }) @@ -1106,12 +1070,12 @@ describe('IncomingTransactionsController', function () { to: '0xe', value: '15', hash: '0xg', - }, 'FAKE_NETWORK') + }, ROPSTEN_CHAIN_ID) assert.deepEqual(result, { blockNumber: 333, id: 54321, - metamaskNetworkId: 'FAKE_NETWORK', + metamaskNetworkId: ROPSTEN_NETWORK_ID, status: 'confirmed', time: 4444000, txParams: {