From d7a812f42fddc39d4673a9fe18307e46ac3d2899 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Thu, 29 Sep 2022 10:39:35 -0600 Subject: [PATCH] Add remaining tests for createInfuraClient (#15717) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add tests for the `block-tracker-inspector` middleware — which makes sure that the block tracker never has a reference to the latest block which is less than a block number that shows up in an RPC method's response — and the Infura middleware — which takes care of sending the request to Infura, and will retry the request up to 5 times if Infura sends back a certain type of error. Note that the `retry-on-empty` middleware is not tested because it currently has a [bug][1] which is making it ineffective. [1]: https://github.com/MetaMask/eth-json-rpc-middleware/issues/139 --- .../network/createInfuraClient.test.js | 71 +- .../network/provider-api-tests/helpers.js | 114 ++- .../provider-api-tests/shared-tests.js | 865 +++++++++++++++++- jest.config.js | 2 +- lavamoat/browserify/beta/policy.json | 138 +-- lavamoat/browserify/flask/policy.json | 142 +-- lavamoat/browserify/main/policy.json | 138 +-- lavamoat/build-system/policy-override.json | 3 +- lavamoat/build-system/policy.json | 97 +- package.json | 2 +- patches/eth-query+2.1.2.patch | 5 +- test/helpers/setup-helper.js | 6 + test/jest/setup.js | 7 + ui/pages/swaps/swaps.util.test.js | 8 +- yarn.lock | 61 +- 15 files changed, 1274 insertions(+), 385 deletions(-) diff --git a/app/scripts/controllers/network/createInfuraClient.test.js b/app/scripts/controllers/network/createInfuraClient.test.js index 4e5fb32b6..404489ece 100644 --- a/app/scripts/controllers/network/createInfuraClient.test.js +++ b/app/scripts/controllers/network/createInfuraClient.test.js @@ -2,7 +2,10 @@ * @jest-environment node */ -import { withInfuraClient } from './provider-api-tests/helpers'; +import { + withMockedInfuraCommunications, + withInfuraClient, +} from './provider-api-tests/helpers'; import { testsForRpcMethodNotHandledByMiddleware, testsForRpcMethodAssumingNoBlockParam, @@ -141,9 +144,36 @@ describe('createInfuraClient', () => { }); describe('eth_getTransactionByHash', () => { - testsForRpcMethodsThatCheckForBlockHashInResponse( - 'eth_getTransactionByHash', - ); + const method = 'eth_getTransactionByHash'; + + testsForRpcMethodsThatCheckForBlockHashInResponse(method); + + it("refreshes the block tracker's current block if it is less than the block number that comes back in the response", async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { method }; + + // The first time a block-cacheable request is made, the latest + // block number is retrieved through the block tracker first. + comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' }); + // This is our request. + comms.mockInfuraRpcCall({ + request, + response: { + result: { + blockNumber: '0x200', + }, + }, + }); + // The block-tracker-inspector middleware will request the latest + // block through the block tracker again. + comms.mockNextBlockTrackerRequest({ blockNumber: '0x300' }); + + await withInfuraClient(async ({ makeRpcCall, blockTracker }) => { + await makeRpcCall(request); + expect(blockTracker.getCurrentBlock()).toStrictEqual('0x300'); + }); + }); + }); }); describe('eth_getTransactionCount', () => { @@ -153,9 +183,36 @@ describe('createInfuraClient', () => { }); describe('eth_getTransactionReceipt', () => { - testsForRpcMethodsThatCheckForBlockHashInResponse( - 'eth_getTransactionReceipt', - ); + const method = 'eth_getTransactionReceipt'; + + testsForRpcMethodsThatCheckForBlockHashInResponse(method); + + it("refreshes the block tracker's current block if it is less than the block number that comes back in the response", async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { method }; + + // The first time a block-cacheable request is made, the latest + // block number is retrieved through the block tracker first. + comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' }); + // This is our request. + comms.mockInfuraRpcCall({ + request, + response: { + result: { + blockNumber: '0x200', + }, + }, + }); + // The block-tracker-inspector middleware will request the latest + // block through the block tracker again. + comms.mockNextBlockTrackerRequest({ blockNumber: '0x300' }); + + await withInfuraClient(async ({ makeRpcCall, blockTracker }) => { + await makeRpcCall(request); + expect(blockTracker.getCurrentBlock()).toStrictEqual('0x300'); + }); + }); + }); }); describe('eth_getUncleByBlockHashAndIndex', () => { diff --git a/app/scripts/controllers/network/provider-api-tests/helpers.js b/app/scripts/controllers/network/provider-api-tests/helpers.js index 9b4c22460..d49cdb7c2 100644 --- a/app/scripts/controllers/network/provider-api-tests/helpers.js +++ b/app/scripts/controllers/network/provider-api-tests/helpers.js @@ -38,37 +38,37 @@ import createInfuraClient from '../createInfuraClient'; */ /** - * @typedef {{ nockScope: NockScope, blockNumber: string }} MockNextBlockTrackerRequestOptions + * @typedef {{ nockScope: NockScope, blockNumber: string }} MockBlockTrackerRequestOptions * - * The options to `mockNextBlockTrackerRequest`. + * The options to `mockNextBlockTrackerRequest` and `mockAllBlockTrackerRequests`. */ /** - * @typedef {{ nockScope: NockScope, request: object, response: object, delay?: number }} MockSuccessfulInfuraRpcCallOptions + * @typedef {{ nockScope: NockScope, request: object, response: object, delay?: number }} MockInfuraRpcCallOptions * - * The options to `mockSuccessfulInfuraRpcCall`. + * The options to `mockInfuraRpcCall`. */ /** - * @typedef {{mockNextBlockTrackerRequest: (options: Omit) => void, mockSuccessfulInfuraRpcCall: (options: Omit) => NockScope}} InfuraCommunications + * @typedef {{mockNextBlockTrackerRequest: (options: Omit) => void, mockAllBlockTrackerRequests: (options: Omit) => void, mockInfuraRpcCall: (options: Omit) => NockScope}} InfuraCommunications * * Provides methods to mock different kinds of requests to Infura. */ /** - * @typedef {{network: string}} MockingInfuraCommunicationsOptions + * @typedef {{network: string}} WithMockedInfuraCommunicationsOptions * * The options bag that `mockingInfuraCommunications` takes. */ /** - * @typedef {(comms: InfuraCommunications) => Promise} MockingInfuraCommunicationsCallback + * @typedef {(comms: InfuraCommunications) => Promise} WithMockedInfuraCommunicationsCallback * * The callback that `mockingInfuraCommunications` takes. */ /** - * @typedef {[MockingInfuraCommunicationsOptions, MockingInfuraCommunicationsCallback] | [MockingInfuraCommunicationsCallback]} MockingInfuraCommunicationsArgs + * @typedef {[WithMockedInfuraCommunicationsOptions, WithMockedInfuraCommunicationsCallback] | [WithMockedInfuraCommunicationsCallback]} WithMockedInfuraCommunicationsArgs * * The arguments to `mockingInfuraCommunications`. */ @@ -111,7 +111,7 @@ function buildScopeForMockingInfuraRequests({ network = 'mainnet' } = {}) { /** * Mocks the next request for the latest block that the block tracker will make. * - * @param {MockNextBlockTrackerRequestOptions} args - The arguments. + * @param {MockBlockTrackerRequestOptions} args - The arguments. * @param {NockScope} args.nockScope - A nock scope (a set of mocked requests * scoped to a certain base URL). * @param {string} args.blockNumber - The block number that the block tracker @@ -121,35 +121,80 @@ async function mockNextBlockTrackerRequest({ nockScope, blockNumber = DEFAULT_LATEST_BLOCK_NUMBER, }) { - await mockSuccessfulInfuraRpcCall({ + await mockInfuraRpcCall({ nockScope, request: { method: 'eth_blockNumber', params: [] }, response: { result: blockNumber }, }); } +/** + * Mocks all requests for the latest block that the block tracker will make. + * + * @param {MockBlockTrackerRequestOptions} args - The arguments. + * @param {NockScope} args.nockScope - A nock scope (a set of mocked requests + * scoped to a certain base URL). + * @param {string} args.blockNumber - The block number that the block tracker + * should report, as a 0x-prefixed hex string. + */ +async function mockAllBlockTrackerRequests({ + nockScope, + blockNumber = DEFAULT_LATEST_BLOCK_NUMBER, +}) { + await mockInfuraRpcCall({ + nockScope, + request: { method: 'eth_blockNumber', params: [] }, + response: { result: blockNumber }, + }).persist(); +} + /** * Mocks a JSON-RPC request sent to Infura with the given response. * - * @param {MockSuccessfulInfuraRpcCallOptions} args - The arguments. + * @param {MockInfuraRpcCallOptions} args - The arguments. * @param {NockScope} args.nockScope - A nock scope (a set of mocked requests * scoped to a certain base URL). * @param {object} args.request - The request data. - * @param {object} args.response - The response that the request should have. - * @param {number} args.delay - The amount of time that should pass before the + * @param {{body: string} | {httpStatus?: number; id?: number; method?: string; params?: string[]}} [args.response] - Information + * concerning the response that the request should have. If a `body` property is + * present, this is taken as the complete response body. If an `httpStatus` + * property is present, then it is taken as the HTTP status code to respond + * with. Properties other than these two are used to build a complete response + * body (including `id` and `jsonrpc` properties). + * @param {Error | string} [args.error] - An error to throw while making the + * request. Takes precedence over `response`. + * @param {number} [args.delay] - The amount of time that should pass before the * request resolves with the response. + * @param {number} [args.times] - The number of times that the request is + * expected to be made. * @returns {NockScope} The nock scope. */ -function mockSuccessfulInfuraRpcCall({ nockScope, request, response, delay }) { - // eth-query always passes `params`, so even if we don't supply this property +function mockInfuraRpcCall({ + nockScope, + request, + response, + error, + delay, + times, +}) { + // eth-query always passes `params`, so even if we don't supply this property, // for consistency with makeRpcCall, assume that the `body` contains it const { method, params = [], ...rest } = request; - const completeResponse = { - id: 1, - jsonrpc: '2.0', - ...response, - }; - const nockRequest = nockScope.post(`/v3/${INFURA_PROJECT_ID}`, { + const httpStatus = response?.httpStatus ?? 200; + let completeResponse; + if (response !== undefined) { + if (response.body === undefined) { + completeResponse = { id: 1, jsonrpc: '2.0' }; + ['id', 'jsonrpc', 'result', 'error'].forEach((prop) => { + if (response[prop] !== undefined) { + completeResponse[prop] = response[prop]; + } + }); + } else { + completeResponse = response.body; + } + } + let nockRequest = nockScope.post(`/v3/${INFURA_PROJECT_ID}`, { jsonrpc: '2.0', method, params, @@ -157,10 +202,19 @@ function mockSuccessfulInfuraRpcCall({ nockScope, request, response, delay }) { }); if (delay !== undefined) { - nockRequest.delay(delay); + nockRequest = nockRequest.delay(delay); + } + + if (times !== undefined) { + nockRequest = nockRequest.times(times); } - return nockRequest.reply(200, completeResponse); + if (error !== undefined) { + return nockRequest.replyWithError(error); + } else if (completeResponse !== undefined) { + return nockRequest.reply(httpStatus, completeResponse); + } + return nockRequest; } /** @@ -189,7 +243,7 @@ function makeRpcCall(ethQuery, request) { /** * Sets up request mocks for requests to Infura. * - * @param {MockingInfuraCommunicationsArgs} args - Either an options bag + a + * @param {WithMockedInfuraCommunicationsArgs} args - Either an options bag + a * function, or just a function. The options bag, at the moment, may contain * `network` (that is, the Infura network; defaults to "mainnet"). The function * is called with an object that allows you to mock different kinds of requests. @@ -202,11 +256,14 @@ export async function withMockedInfuraCommunications(...args) { const nockScope = buildScopeForMockingInfuraRequests({ network }); const curriedMockNextBlockTrackerRequest = (localOptions) => mockNextBlockTrackerRequest({ nockScope, ...localOptions }); - const curriedMockSuccessfulInfuraRpcCall = (localOptions) => - mockSuccessfulInfuraRpcCall({ nockScope, ...localOptions }); + const curriedMockAllBlockTrackerRequests = (localOptions) => + mockAllBlockTrackerRequests({ nockScope, ...localOptions }); + const curriedMockInfuraRpcCall = (localOptions) => + mockInfuraRpcCall({ nockScope, ...localOptions }); const comms = { mockNextBlockTrackerRequest: curriedMockNextBlockTrackerRequest, - mockSuccessfulInfuraRpcCall: curriedMockSuccessfulInfuraRpcCall, + mockAllBlockTrackerRequests: curriedMockAllBlockTrackerRequests, + mockInfuraRpcCall: curriedMockInfuraRpcCall, }; try { @@ -258,9 +315,10 @@ export async function withInfuraClient(...args) { // depends on `setTimeout`) const clock = sinon.useFakeTimers(); const client = { + blockTracker, + clock, makeRpcCall: curriedMakeRpcCall, makeRpcCallsInSeries, - clock, }; try { diff --git a/app/scripts/controllers/network/provider-api-tests/shared-tests.js b/app/scripts/controllers/network/provider-api-tests/shared-tests.js index aafa2155a..c28855435 100644 --- a/app/scripts/controllers/network/provider-api-tests/shared-tests.js +++ b/app/scripts/controllers/network/provider-api-tests/shared-tests.js @@ -9,6 +9,57 @@ import { buildRequestWithReplacedBlockParam, } from './helpers'; +const originalSetTimeout = setTimeout; + +/** + * Some middleware contain logic which retries the request if some condition + * applies. This retrying always happens out of band via `setTimeout`, and + * because we are stubbing time via Jest's fake timers, we have to manually + * advance the clock so that the `setTimeout` handlers get fired. We don't know + * when these timers will get created, however, so we have to keep advancing + * timers until the request has been made an appropriate number of times. + * Unfortunately we don't have a good way to know how many times a request has + * been retried, but the good news is that the middleware won't end, and thus + * the promise which the RPC call returns won't get fulfilled, until all retries + * have been made. + * + * @param promise - The promise which is returned by the RPC call. + * @param clock - A Sinon clock object which can be used to advance to the next + * `setTimeout` handler. + */ +async function waitForPromiseToBeFulfilledAfterRunningAllTimers( + promise, + clock, +) { + let hasPromiseBeenFulfilled = false; + let numTimesClockHasBeenAdvanced = 0; + + promise + .catch(() => { + // This is used to silence Node.js warnings about the rejection + // being handled asynchronously. The error is handled later when + // `promise` is awaited. + }) + .finally(() => { + hasPromiseBeenFulfilled = true; + }); + + // `isPromiseFulfilled` is modified asynchronously. + /* eslint-disable-next-line no-unmodified-loop-condition */ + while (!hasPromiseBeenFulfilled && numTimesClockHasBeenAdvanced < 15) { + clock.runAll(); + await new Promise((resolve) => originalSetTimeout(resolve, 10)); + numTimesClockHasBeenAdvanced += 1; + } + + return promise; +} + +/** + * Defines tests which exercise the behavior exhibited by an RPC method that + * does not support params (which affects how the method is cached). + */ +/* eslint-disable-next-line jest/no-export */ export function testsForRpcMethodNotHandledByMiddleware( method, { numberOfParameters }, @@ -25,7 +76,7 @@ export function testsForRpcMethodNotHandledByMiddleware( // number is retrieved through the block tracker first. It doesn't // matter what this is — it's just used as a cache key. comms.mockNextBlockTrackerRequest(); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request, response: { result: expectedResult }, }); @@ -55,7 +106,7 @@ export function testsForRpcMethodAssumingNoBlockParam(method) { // number is retrieved through the block tracker first. It doesn't // matter what this is — it's just used as a cache key. comms.mockNextBlockTrackerRequest(); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[0] }, }); @@ -78,12 +129,12 @@ export function testsForRpcMethodAssumingNoBlockParam(method) { // the second RPC request, but rather because we call `clock.runAll()` // below. comms.mockNextBlockTrackerRequest({ blockNumber: '0x1' }); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[0] }, }); comms.mockNextBlockTrackerRequest({ blockNumber: '0x2' }); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[1], response: { result: mockResults[1] }, }); @@ -112,11 +163,11 @@ export function testsForRpcMethodAssumingNoBlockParam(method) { // number is retrieved through the block tracker first. It doesn't // matter what this is — it's just used as a cache key. comms.mockNextBlockTrackerRequest(); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[0] }, }); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[1], response: { result: mockResults[1] }, }); @@ -129,6 +180,265 @@ export function testsForRpcMethodAssumingNoBlockParam(method) { }); }, ); + + it('queues requests while a previous identical call is still pending, then runs the queue when it finishes, reusing the result from the first request', async () => { + const requests = [{ method }, { method }, { method }]; + const mockResults = ['first result', 'second result', 'third result']; + + await withMockedInfuraCommunications(async (comms) => { + // The first time a block-cacheable request is made, the latest block + // number is retrieved through the block tracker first. It doesn't + // matter what this is — it's just used as a cache key. + comms.mockNextBlockTrackerRequest(); + comms.mockInfuraRpcCall({ + request: requests[0], + response: { result: mockResults[0] }, + delay: 100, + }); + comms.mockInfuraRpcCall({ + request: requests[1], + response: { result: mockResults[1] }, + }); + comms.mockInfuraRpcCall({ + request: requests[2], + response: { result: mockResults[2] }, + }); + + const results = await withInfuraClient(async (client) => { + const resultPromises = [ + client.makeRpcCall(requests[0]), + client.makeRpcCall(requests[1]), + client.makeRpcCall(requests[2]), + ]; + const firstResult = await resultPromises[0]; + // The inflight cache middleware uses setTimeout to run the handlers, + // so run them now + client.clock.runAll(); + const remainingResults = await Promise.all(resultPromises.slice(1)); + return [firstResult, ...remainingResults]; + }); + + expect(results).toStrictEqual([ + mockResults[0], + mockResults[0], + mockResults[0], + ]); + }); + }); + + it('throws a custom error if the request to Infura returns a 405 response', async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { method }; + + // The first time a block-cacheable request is made, the latest block + // number is retrieved through the block tracker first. It doesn't + // matter what this is — it's just used as a cache key. + comms.mockNextBlockTrackerRequest(); + comms.mockInfuraRpcCall({ + request, + response: { + httpStatus: 405, + }, + }); + const promiseForResult = withInfuraClient(async ({ makeRpcCall }) => + makeRpcCall(request), + ); + + await expect(promiseForResult).rejects.toThrow( + 'The method does not exist / is not available', + ); + }); + }); + + it('throws a custom error if the request to Infura returns a 429 response', async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { method }; + + // The first time a block-cacheable request is made, the latest block + // number is retrieved through the block tracker first. It doesn't + // matter what this is — it's just used as a cache key. + comms.mockNextBlockTrackerRequest(); + comms.mockInfuraRpcCall({ + request, + response: { + httpStatus: 429, + }, + }); + const promiseForResult = withInfuraClient(async ({ makeRpcCall }) => + makeRpcCall(request), + ); + + await expect(promiseForResult).rejects.toThrow( + 'Request is being rate limited', + ); + }); + }); + + it('throws a custom error if the request to Infura returns a response that is not 405, 429, 503, or 504', async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { method }; + + // The first time a block-cacheable request is made, the latest block + // number is retrieved through the block tracker first. It doesn't + // matter what this is — it's just used as a cache key. + comms.mockNextBlockTrackerRequest(); + comms.mockInfuraRpcCall({ + request, + response: { + id: 12345, + jsonrpc: '2.0', + error: 'some error', + httpStatus: 420, + }, + }); + const promiseForResult = withInfuraClient(async ({ makeRpcCall }) => + makeRpcCall(request), + ); + + await expect(promiseForResult).rejects.toThrow( + '{"id":12345,"jsonrpc":"2.0","error":"some error"}', + ); + }); + }); + + [503, 504].forEach((httpStatus) => { + it(`retries the request to Infura up to 5 times if it returns a ${httpStatus} response, returning the successful result if there is one on the 5th try`, async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { method }; + + // The first time a block-cacheable request is made, the latest block + // number is retrieved through the block tracker first. It doesn't + // matter what this is — it's just used as a cache key. + comms.mockNextBlockTrackerRequest(); + // Here we have the request fail for the first 4 tries, then succeed + // on the 5th try. + comms.mockInfuraRpcCall({ + request, + response: { + error: 'Some error', + httpStatus, + }, + times: 4, + }); + comms.mockInfuraRpcCall({ + request, + response: { + result: 'the result', + httpStatus: 200, + }, + }); + const result = await withInfuraClient( + async ({ makeRpcCall, clock }) => { + return await waitForPromiseToBeFulfilledAfterRunningAllTimers( + makeRpcCall(request), + clock, + ); + }, + ); + + expect(result).toStrictEqual('the result'); + }); + }); + + it(`causes a request to fail with a custom error if the request to Infura returns a ${httpStatus} response 5 times in a row`, async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { method }; + + // The first time a block-cacheable request is made, the latest block + // number is retrieved through the block tracker first. It doesn't + // matter what this is — it's just used as a cache key. + comms.mockNextBlockTrackerRequest(); + comms.mockInfuraRpcCall({ + request, + response: { + error: 'Some error', + httpStatus, + }, + times: 5, + }); + const promiseForResult = withInfuraClient( + async ({ makeRpcCall, clock }) => { + return await waitForPromiseToBeFulfilledAfterRunningAllTimers( + makeRpcCall(request), + clock, + ); + }, + ); + + await expect(promiseForResult).rejects.toThrow( + /^InfuraProvider - cannot complete request\. All retries exhausted\..+Gateway timeout/su, + ); + }); + }); + }); + + ['ETIMEDOUT', 'ECONNRESET', 'SyntaxError'].forEach((errorMessagePrefix) => { + it(`retries the request to Infura up to 5 times if an "${errorMessagePrefix}" error is thrown while making the request, returning the successful result if there is one on the 5th try`, async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { method }; + + // The first time a block-cacheable request is made, the latest block + // number is retrieved through the block tracker first. It doesn't + // matter what this is — it's just used as a cache key. + comms.mockNextBlockTrackerRequest(); + // Here we have the request fail for the first 4 tries, then succeed + // on the 5th try. + comms.mockInfuraRpcCall({ + request, + error: `${errorMessagePrefix}: Some message`, + times: 4, + }); + comms.mockInfuraRpcCall({ + request, + response: { + result: 'the result', + httpStatus: 200, + }, + }); + const result = await withInfuraClient( + async ({ makeRpcCall, clock }) => { + return await waitForPromiseToBeFulfilledAfterRunningAllTimers( + makeRpcCall(request), + clock, + ); + }, + ); + + expect(result).toStrictEqual('the result'); + }); + }); + + it(`causes a request to fail with a custom error if an "${errorMessagePrefix}" error is thrown while making the request to Infura 5 times in a row`, async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { method }; + + // The first time a block-cacheable request is made, the latest block + // number is retrieved through the block tracker first. It doesn't + // matter what this is — it's just used as a cache key. + comms.mockNextBlockTrackerRequest(); + comms.mockInfuraRpcCall({ + request, + error: `${errorMessagePrefix}: Some message`, + times: 5, + }); + const promiseForResult = withInfuraClient( + async ({ makeRpcCall, clock }) => { + return await waitForPromiseToBeFulfilledAfterRunningAllTimers( + makeRpcCall(request), + clock, + ); + }, + ); + + await expect(promiseForResult).rejects.toThrow( + new RegExp( + `^InfuraProvider - cannot complete request\\. All retries exhausted\\..+${errorMessagePrefix}: Some message`, + 'su', + ), + ); + }); + }); + }); } /** @@ -148,7 +458,7 @@ export function testsForRpcMethodsThatCheckForBlockHashInResponse(method) { // number is retrieved through the block tracker first. It doesn't // matter what this is — it's just used as a cache key. comms.mockNextBlockTrackerRequest(); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[0] }, }); @@ -172,12 +482,12 @@ export function testsForRpcMethodsThatCheckForBlockHashInResponse(method) { // because of the second RPC request, but rather because we call // `clock.runAll()` below. comms.mockNextBlockTrackerRequest({ blockNumber: '0x1' }); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[0] }, }); comms.mockNextBlockTrackerRequest({ blockNumber: '0x2' }); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[1], response: { result: mockResults[1] }, }); @@ -206,11 +516,11 @@ export function testsForRpcMethodsThatCheckForBlockHashInResponse(method) { // number is retrieved through the block tracker first. It doesn't // matter what this is — it's just used as a cache key. comms.mockNextBlockTrackerRequest(); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[0] }, }); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[1], response: { result: mockResults[1] }, }); @@ -219,6 +529,7 @@ export function testsForRpcMethodsThatCheckForBlockHashInResponse(method) { makeRpcCallsInSeries(requests), ); + // TODO: Does this work? expect(results).toStrictEqual(mockResults); }); }, @@ -236,11 +547,11 @@ export function testsForRpcMethodsThatCheckForBlockHashInResponse(method) { // number is retrieved through the block tracker first. It doesn't // matter what this is — it's just used as a cache key. comms.mockNextBlockTrackerRequest(); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[0] }, }); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[1], response: { result: mockResults[1] }, }); @@ -265,11 +576,11 @@ export function testsForRpcMethodsThatCheckForBlockHashInResponse(method) { // number is retrieved through the block tracker first. It doesn't // matter what this is — it's just used as a cache key. comms.mockNextBlockTrackerRequest(); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[0] }, }); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[1], response: { result: mockResults[1] }, }); @@ -298,11 +609,11 @@ export function testsForRpcMethodsThatCheckForBlockHashInResponse(method) { // number is retrieved through the block tracker first. It doesn't // matter what this is — it's just used as a cache key. comms.mockNextBlockTrackerRequest(); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[0] }, }); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[1], response: { result: mockResults[1] }, }); @@ -354,7 +665,7 @@ export function testsForRpcMethodSupportingBlockParam( // The block-ref middleware will make the request as specified // except that the block param is replaced with the latest block // number. - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: buildRequestWithReplacedBlockParam( requests[0], blockParamIndex, @@ -364,7 +675,7 @@ export function testsForRpcMethodSupportingBlockParam( }); // Note that the block-ref middleware will still allow the original // request to go through. - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[0] }, }); @@ -394,7 +705,7 @@ export function testsForRpcMethodSupportingBlockParam( // The block-ref middleware will make the request as specified // except that the block param is replaced with the latest block // number. - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: buildRequestWithReplacedBlockParam( requests[0], blockParamIndex, @@ -404,18 +715,18 @@ export function testsForRpcMethodSupportingBlockParam( }); // Note that the block-ref middleware will still allow the original // request to go through. - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[0] }, }); comms.mockNextBlockTrackerRequest({ blockNumber: '0x200' }); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[1], response: { result: mockResults[1] }, }); // The previous two requests will happen again, with a different block // number, in the same order. - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: buildRequestWithReplacedBlockParam( requests[0], blockParamIndex, @@ -423,7 +734,7 @@ export function testsForRpcMethodSupportingBlockParam( ), response: { result: mockResults[1] }, }); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[1] }, }); @@ -461,7 +772,7 @@ export function testsForRpcMethodSupportingBlockParam( // The block-ref middleware will make the request as specified // except that the block param is replaced with the latest block // number. - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: buildRequestWithReplacedBlockParam( requests[0], blockParamIndex, @@ -471,12 +782,12 @@ export function testsForRpcMethodSupportingBlockParam( }); // Note that the block-ref middleware will still allow the original // request to go through. - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[0] }, }); // The previous two requests will happen again, in the same order. - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: buildRequestWithReplacedBlockParam( requests[0], blockParamIndex, @@ -484,7 +795,7 @@ export function testsForRpcMethodSupportingBlockParam( ), response: { result: mockResults[1] }, }); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[1] }, }); @@ -497,6 +808,420 @@ export function testsForRpcMethodSupportingBlockParam( }); }, ); + + it('queues requests while a previous identical call is still pending, then runs the queue when it finishes, reusing the result from the first request', async () => { + const requests = [{ method }, { method }, { method }]; + const mockResults = ['first result', 'second result', 'third result']; + + await withMockedInfuraCommunications(async (comms) => { + // The first time a block-cacheable request is made, the + // block-cache middleware will request the latest block number + // through the block tracker to determine the cache key. Later, + // the block-ref middleware will request the latest block number + // again to resolve the value of "latest", but the block number is + // cached once made, so we only need to mock the request once. + comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' }); + // The block-ref middleware will make the request as specified + // except that the block param is replaced with the latest block + // number. + comms.mockInfuraRpcCall({ + request: buildRequestWithReplacedBlockParam( + requests[0], + blockParamIndex, + '0x100', + ), + response: { result: mockResults[0] }, + }); + // This is the original request as below, which the block-ref + // middleware will allow through, except that we delay it. + comms.mockInfuraRpcCall({ + request: requests[0], + response: { result: mockResults[0] }, + delay: 100, + }); + // The previous two requests will happen again, in the same order. + comms.mockInfuraRpcCall({ + request: buildRequestWithReplacedBlockParam( + requests[1], + blockParamIndex, + '0x100', + ), + response: { result: mockResults[1] }, + }); + comms.mockInfuraRpcCall({ + request: requests[1], + response: { result: mockResults[1] }, + }); + comms.mockInfuraRpcCall({ + request: buildRequestWithReplacedBlockParam( + requests[2], + blockParamIndex, + '0x100', + ), + response: { result: mockResults[2] }, + }); + comms.mockInfuraRpcCall({ + request: requests[2], + response: { result: mockResults[2] }, + }); + + const results = await withInfuraClient(async (client) => { + const resultPromises = [ + client.makeRpcCall(requests[0]), + client.makeRpcCall(requests[1]), + client.makeRpcCall(requests[2]), + ]; + const firstResult = await resultPromises[0]; + // The inflight cache middleware uses setTimeout to run the + // handlers, so run them now + client.clock.runAll(); + const remainingResults = await Promise.all(resultPromises.slice(1)); + return [firstResult, ...remainingResults]; + }); + + expect(results).toStrictEqual([ + mockResults[0], + mockResults[0], + mockResults[0], + ]); + }); + }); + + if (blockParamType === 'none') { + it('throws a custom error if the request to Infura returns a 405 response', async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { method }; + + // The first time a block-cacheable request is made, the + // block-cache middleware will request the latest block number + // through the block tracker to determine the cache key. Later, + // the block-ref middleware will request the latest block number + // again to resolve the value of "latest", but the block number is + // cached once made, so we only need to mock the request once. + comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' }); + // The block-ref middleware will make the request as specified + // except that the block param is replaced with the latest block + // number. + // + // Note, however, that the block-ref middleware doesn't run the + // original request, as it fails before it gets to that point, so + // there is no need to mock the request again. + comms.mockInfuraRpcCall({ + request: buildRequestWithReplacedBlockParam( + request, + blockParamIndex, + '0x100', + ), + response: { + httpStatus: 405, + }, + }); + const promiseForResult = withInfuraClient(async ({ makeRpcCall }) => + makeRpcCall(request), + ); + + await expect(promiseForResult).rejects.toThrow( + 'The method does not exist / is not available', + ); + }); + }); + + it('throws a custom error if the request to Infura returns a 429 response', async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { method }; + + // The first time a block-cacheable request is made, the + // block-cache middleware will request the latest block number + // through the block tracker to determine the cache key. Later, + // the block-ref middleware will request the latest block number + // again to resolve the value of "latest", but the block number is + // cached once made, so we only need to mock the request once. + comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' }); + // The block-ref middleware will make the request as specified + // except that the block param is replaced with the latest block + // number. + // + // Note, however, that the block-ref middleware doesn't run the + // original request, as it fails before it gets to that point, so + // there is no need to mock the request again. + comms.mockInfuraRpcCall({ + request: buildRequestWithReplacedBlockParam( + request, + blockParamIndex, + '0x100', + ), + response: { + httpStatus: 429, + }, + }); + const promiseForResult = withInfuraClient(async ({ makeRpcCall }) => + makeRpcCall(request), + ); + + await expect(promiseForResult).rejects.toThrow( + 'Request is being rate limited', + ); + }); + }); + + it('throws a custom error if the request to Infura returns a response that is not 405, 429, 503, or 504', async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { method }; + + // The first time a block-cacheable request is made, the + // block-cache middleware will request the latest block number + // through the block tracker to determine the cache key. Later, + // the block-ref middleware will request the latest block number + // again to resolve the value of "latest", but the block number is + // cached once made, so we only need to mock the request once. + comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' }); + // The block-ref middleware will make the request as specified + // except that the block param is replaced with the latest block + // number. + // + // Note, however, that the block-ref middleware doesn't run the + // original request, as it fails before it gets to that point, so + // there is no need to mock the request again. + comms.mockInfuraRpcCall({ + request: buildRequestWithReplacedBlockParam( + request, + blockParamIndex, + '0x100', + ), + response: { + id: 12345, + jsonrpc: '2.0', + error: 'some error', + httpStatus: 420, + }, + }); + const promiseForResult = withInfuraClient(async ({ makeRpcCall }) => + makeRpcCall(request), + ); + + await expect(promiseForResult).rejects.toThrow( + '{"id":12345,"jsonrpc":"2.0","error":"some error"}', + ); + }); + }); + + [503, 504].forEach((httpStatus) => { + it(`retries the request to Infura up to 5 times if it returns a ${httpStatus} response, returning the successful result if there is one on the 5th try`, async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { method }; + + // The first time a block-cacheable request is made, the + // block-cache middleware will request the latest block number + // through the block tracker to determine the cache key. Later, + // the block-ref middleware will request the latest block number + // again to resolve the value of "latest", but the block number is + // cached once made, so we only need to mock the request once. + comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' }); + // The block-ref middleware will make the request as specified + // except that the block param is replaced with the latest block + // number. + // + // Here we have the request fail for the first 4 tries, then succeed + // on the 5th try. + comms.mockInfuraRpcCall({ + request: buildRequestWithReplacedBlockParam( + request, + blockParamIndex, + '0x100', + ), + response: { + error: 'some error', + httpStatus, + }, + times: 4, + }); + comms.mockInfuraRpcCall({ + request: buildRequestWithReplacedBlockParam( + request, + blockParamIndex, + '0x100', + ), + response: { + result: 'the result', + httpStatus: 200, + }, + }); + // Note that the block-ref middleware will still allow the original + // request to go through. + comms.mockInfuraRpcCall({ + request, + response: { + result: 'the result', + httpStatus: 200, + }, + }); + const result = await withInfuraClient( + async ({ makeRpcCall, clock }) => { + return await waitForPromiseToBeFulfilledAfterRunningAllTimers( + makeRpcCall(request), + clock, + ); + }, + ); + + expect(result).toStrictEqual('the result'); + }); + }); + + it(`causes a request to fail with a custom error if the request to Infura returns a ${httpStatus} response 5 times in a row`, async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { method }; + + // The first time a block-cacheable request is made, the + // block-cache middleware will request the latest block number + // through the block tracker to determine the cache key. Later, + // the block-ref middleware will request the latest block number + // again to resolve the value of "latest", but the block number is + // cached once made, so we only need to mock the request once. + comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' }); + // The block-ref middleware will make the request as specified + // except that the block param is replaced with the latest block + // number. + // + // Note, however, that the block-ref middleware doesn't run the + // original request, as it fails before it gets to that point, so + // there is no need to mock the request again. + comms.mockInfuraRpcCall({ + request: buildRequestWithReplacedBlockParam( + request, + blockParamIndex, + '0x100', + ), + response: { + error: 'Some error', + httpStatus, + }, + times: 5, + }); + const promiseForResult = withInfuraClient( + async ({ makeRpcCall, clock }) => { + return await waitForPromiseToBeFulfilledAfterRunningAllTimers( + makeRpcCall(request), + clock, + ); + }, + ); + + await expect(promiseForResult).rejects.toThrow( + /^InfuraProvider - cannot complete request\. All retries exhausted\..+Gateway timeout/su, + ); + }); + }); + }); + + ['ETIMEDOUT', 'ECONNRESET', 'SyntaxError'].forEach( + (errorMessagePrefix) => { + it(`retries the request to Infura up to 5 times if an "${errorMessagePrefix}" error is thrown while making the request, returning the successful result if there is one on the 5th try`, async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { method }; + + // The first time a block-cacheable request is made, the + // block-cache middleware will request the latest block number + // through the block tracker to determine the cache key. Later, + // the block-ref middleware will request the latest block number + // again to resolve the value of "latest", but the block number is + // cached once made, so we only need to mock the request once. + comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' }); + // The block-ref middleware will make the request as specified + // except that the block param is replaced with the latest block + // number. + // + // Here we have the request fail for the first 4 tries, then + // succeed on the 5th try. + comms.mockInfuraRpcCall({ + request: buildRequestWithReplacedBlockParam( + request, + blockParamIndex, + '0x100', + ), + error: `${errorMessagePrefix}: Some message`, + times: 4, + }); + comms.mockInfuraRpcCall({ + request: buildRequestWithReplacedBlockParam( + request, + blockParamIndex, + '0x100', + ), + response: { + result: 'the result', + httpStatus: 200, + }, + }); + // Note that the block-ref middleware will still allow the + // original request to go through. + comms.mockInfuraRpcCall({ + request, + response: { + result: 'the result', + httpStatus: 200, + }, + }); + const result = await withInfuraClient( + async ({ makeRpcCall, clock }) => { + return await waitForPromiseToBeFulfilledAfterRunningAllTimers( + makeRpcCall(request), + clock, + ); + }, + ); + + expect(result).toStrictEqual('the result'); + }); + }); + + it(`causes a request to fail with a custom error if an "${errorMessagePrefix}" error is thrown while making the request to Infura 5 times in a row`, async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { method }; + + // The first time a block-cacheable request is made, the + // block-cache middleware will request the latest block number + // through the block tracker to determine the cache key. Later, + // the block-ref middleware will request the latest block number + // again to resolve the value of "latest", but the block number is + // cached once made, so we only need to mock the request once. + comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' }); + // The block-ref middleware will make the request as specified + // except that the block param is replaced with the latest block + // number. + // + // Note, however, that the block-ref middleware doesn't run the + // original request, as it fails before it gets to that point, so + // there is no need to mock the request again. + comms.mockInfuraRpcCall({ + request: buildRequestWithReplacedBlockParam( + request, + blockParamIndex, + '0x100', + ), + error: `${errorMessagePrefix}: Some message`, + times: 5, + }); + const promiseForResult = withInfuraClient( + async ({ makeRpcCall, clock }) => { + return await waitForPromiseToBeFulfilledAfterRunningAllTimers( + makeRpcCall(request), + clock, + ); + }, + ); + + await expect(promiseForResult).rejects.toThrow( + new RegExp( + `^InfuraProvider - cannot complete request\\. All retries exhausted\\..+${errorMessagePrefix}: Some message`, + 'su', + ), + ); + }); + }); + }, + ); + } }); describe.each([ @@ -518,7 +1243,7 @@ export function testsForRpcMethodSupportingBlockParam( // tracker to determine the cache key. This block number doesn't // matter. comms.mockNextBlockTrackerRequest(); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[0] }, }); @@ -545,12 +1270,12 @@ export function testsForRpcMethodSupportingBlockParam( // occur because of the second RPC request, but rather because we // call `clock.runAll()` below. comms.mockNextBlockTrackerRequest({ blockNumber: '0x1' }); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[0] }, }); comms.mockNextBlockTrackerRequest({ blockNumber: '0x2' }); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[1], response: { result: mockResults[1] }, }); @@ -582,11 +1307,11 @@ export function testsForRpcMethodSupportingBlockParam( // number is retrieved through the block tracker first. It doesn't // matter what this is — it's just used as a cache key. comms.mockNextBlockTrackerRequest(); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[0] }, }); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[1], response: { result: mockResults[1] }, }); @@ -622,7 +1347,7 @@ export function testsForRpcMethodSupportingBlockParam( // block number is retrieved through the block tracker first. It // doesn't matter what this is — it's just used as a cache key. comms.mockNextBlockTrackerRequest(); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[0] }, }); @@ -654,11 +1379,11 @@ export function testsForRpcMethodSupportingBlockParam( // number is retrieved through the block tracker first. It doesn't // matter what this is — it's just used as a cache key. comms.mockNextBlockTrackerRequest(); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: 'first result' }, }); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[1], response: { result: 'second result' }, }); @@ -670,6 +1395,70 @@ export function testsForRpcMethodSupportingBlockParam( expect(results).toStrictEqual(['first result', 'second result']); }); }); + + it('makes an additional request to Infura if the given block number matches the latest block number', async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { + method, + params: buildMockParamsWithBlockParamAt(blockParamIndex, '0x100'), + }; + + // The first time a block-cacheable request is made, the latest + // block number is retrieved through the block tracker first. This + // also happens within the retry-on-empty middleware (although the + // latest block is cached by now). + comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' }); + // The retry-on-empty middleware will make an explicit request. + comms.mockInfuraRpcCall({ + request, + response: { result: 'this result gets overwritten' }, + }); + // Note that the retry-on-empty middleware will still allow the + // original request to go through. + comms.mockInfuraRpcCall({ + request, + response: { result: 'the actual result' }, + }); + + const result = await withInfuraClient(({ makeRpcCall }) => + makeRpcCall(request), + ); + + expect(result).toStrictEqual('the actual result'); + }); + }); + + it('makes an additional request to Infura if the given block number is less than the latest block number', async () => { + await withMockedInfuraCommunications(async (comms) => { + const request = { + method, + params: buildMockParamsWithBlockParamAt(blockParamIndex, '0x50'), + }; + + // The first time a block-cacheable request is made, the latest + // block number is retrieved through the block tracker first. This + // also happens within the retry-on-empty middleware (although the + // latest block is cached by now). + comms.mockNextBlockTrackerRequest({ blockNumber: '0x100' }); + // The retry-on-empty middleware will make an explicit request. + comms.mockInfuraRpcCall({ + request, + response: { result: 'this result gets overwritten' }, + }); + // Note that the retry-on-empty middleware will still allow the + // original request to go through. + comms.mockInfuraRpcCall({ + request, + response: { result: 'the actual result' }, + }); + + const result = await withInfuraClient(({ makeRpcCall }) => + makeRpcCall(request), + ); + + expect(result).toStrictEqual('the actual result'); + }); + }); } }); @@ -688,11 +1477,11 @@ export function testsForRpcMethodSupportingBlockParam( // block number is retrieved through the block tracker first. It // doesn't matter what this is — it's just used as a cache key. comms.mockNextBlockTrackerRequest(); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[0], response: { result: mockResults[0] }, }); - comms.mockSuccessfulInfuraRpcCall({ + comms.mockInfuraRpcCall({ request: requests[1], response: { result: mockResults[1] }, }); diff --git a/jest.config.js b/jest.config.js index 04b26dfe6..1c8cfe7ff 100644 --- a/jest.config.js +++ b/jest.config.js @@ -49,7 +49,7 @@ module.exports = { '/app/scripts/lib/**/*.test.js', '/app/scripts/migrations/*.test.js', '/app/scripts/platforms/*.test.js', - 'app/scripts/controllers/network/**/*.test.js', + '/app/scripts/controllers/network/**/*.test.js', '/app/scripts/controllers/permissions/**/*.test.js', '/app/scripts/flask/**/*.test.js', '/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js', diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index fc15ef26b..2e9433adf 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -288,7 +288,7 @@ "browserify>insert-module-globals>is-buffer": true, "browserify>timers-browserify": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs-mini": { @@ -388,7 +388,7 @@ "3box>ipfs>multibase": true, "browserify>assert": true, "browserify>buffer": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>dlv": { @@ -450,7 +450,7 @@ "browserify>assert": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>ipfs-bitswap>bignumber.js": { @@ -520,7 +520,7 @@ "browserify>assert": true, "browserify>browser-resolve": true, "browserify>buffer": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>ipfs-mfs>hamt-sharding": { @@ -567,7 +567,7 @@ "browserify>path-browserify": true, "browserify>timers-browserify": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>ipfs-repo>bignumber.js": { @@ -811,7 +811,7 @@ "3box>ipfs>protons": true, "base32-encode": true, "browserify>buffer": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>is-ipfs": { @@ -850,7 +850,7 @@ "browserify>insert-module-globals>is-buffer": true, "browserify>process": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -866,7 +866,7 @@ "3box>ipfs>peer-info": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p-crypto": { @@ -979,7 +979,7 @@ "browserify>events": true, "browserify>insert-module-globals>is-buffer": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "promise-to-callback": true } }, @@ -1102,7 +1102,7 @@ "browserify>assert": true, "browserify>buffer": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1161,7 +1161,7 @@ "3box>ipfs>stream-to-pull-stream": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1177,7 +1177,7 @@ "3box>ipfs>libp2p-webrtc-star>simple-peer>readable-stream": true, "browserify>buffer": true, "ethereumjs-wallet>randombytes": true, - "madge>debug": true, + "nock>debug": true, "pumpify>inherits": true } }, @@ -1377,7 +1377,7 @@ "3box>ipfs>multiaddr": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1399,7 +1399,7 @@ "browserify>buffer": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true, "uuid": true } @@ -1449,7 +1449,7 @@ "3box>ipfs>multiaddr-to-uri": true, "3box>ipfs>pull-mplex>interface-connection": true, "browserify>os-browserify": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p-websockets>pull-ws": { @@ -1478,7 +1478,7 @@ "packages": { "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor": true, "browserify>events": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor": { @@ -1518,7 +1518,7 @@ "3box>ipfs>pull-stream": true, "browserify>assert": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub": { @@ -1535,7 +1535,7 @@ "browserify>events": true, "browserify>insert-module-globals>is-buffer": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub>time-cache": { @@ -1555,7 +1555,7 @@ "3box>ipfs>libp2p-secio>pull-handshake": true, "3box>ipfs>pull-stream": true, "browserify>events": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p>libp2p-switch": { @@ -1578,7 +1578,7 @@ "browserify>assert": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1601,7 +1601,7 @@ "3box>ipfs>pull-stream": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1631,7 +1631,7 @@ "browserify>assert": true, "browserify>buffer": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1806,7 +1806,7 @@ "browserify>buffer": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>pull-mplex>interface-connection": { @@ -3102,7 +3102,7 @@ "packages": { "@metamask/eth-json-rpc-infura>@metamask/utils>superstruct": true, "eslint>fast-deep-equal": true, - "madge>debug": true + "nock>debug": true } }, "@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": { @@ -3231,15 +3231,36 @@ }, "packages": { "@babel/runtime": true, + "@metamask/eth-token-tracker>deep-equal": true, "@metamask/eth-token-tracker>eth-block-tracker": true, "@metamask/eth-token-tracker>ethjs": true, "@metamask/eth-token-tracker>human-standard-token-abi": true, "ethjs-contract": true, "ethjs-query": true, - "nock>deep-equal": true, "safe-event-emitter": true } }, + "@metamask/eth-token-tracker>deep-equal": { + "packages": { + "@metamask/eth-token-tracker>deep-equal>is-arguments": true, + "@metamask/eth-token-tracker>deep-equal>is-date-object": true, + "enzyme>is-regex": true, + "enzyme>object-is": true, + "mocha>object.assign>object-keys": true, + "string.prototype.matchall>regexp.prototype.flags": true + } + }, + "@metamask/eth-token-tracker>deep-equal>is-arguments": { + "packages": { + "koa>is-generator-function>has-tostringtag": true, + "string.prototype.matchall>call-bind": true + } + }, + "@metamask/eth-token-tracker>deep-equal>is-date-object": { + "packages": { + "koa>is-generator-function>has-tostringtag": true + } + }, "@metamask/eth-token-tracker>eth-block-tracker": { "globals": { "clearTimeout": true, @@ -3670,6 +3691,11 @@ "localStorage": true } }, + "@storybook/components>qs": { + "packages": { + "string.prototype.matchall>side-channel": true + } + }, "@storybook/react>@storybook/store>stable": { "globals": { "define": true @@ -3690,7 +3716,7 @@ "browserify>buffer": true, "browserify>util": true, "gulp-dart-sass>lodash.clonedeep": true, - "madge>debug": true, + "nock>debug": true, "semver": true } }, @@ -3913,7 +3939,7 @@ "@truffle/codec>web3-utils": true, "@truffle/decoder>@truffle/source-map-utils": true, "@truffle/decoder>bn.js": true, - "madge>debug": true + "nock>debug": true } }, "@truffle/decoder>@truffle/source-map-utils": { @@ -3923,7 +3949,7 @@ "@truffle/decoder>@truffle/source-map-utils>@truffle/code-utils": true, "@truffle/decoder>@truffle/source-map-utils>json-pointer": true, "@truffle/decoder>@truffle/source-map-utils>node-interval-tree": true, - "madge>debug": true + "nock>debug": true } }, "@truffle/decoder>@truffle/source-map-utils>@truffle/code-utils": { @@ -4516,7 +4542,7 @@ "packages": { "eslint>fast-deep-equal": true, "eth-block-tracker>@metamask/utils>superstruct": true, - "madge>debug": true + "nock>debug": true } }, "eth-ens-namehash": { @@ -4586,7 +4612,7 @@ "packages": { "eslint>fast-deep-equal": true, "eth-json-rpc-middleware>@metamask/utils>superstruct": true, - "madge>debug": true + "nock>debug": true } }, "eth-json-rpc-middleware>eth-sig-util": { @@ -4918,10 +4944,10 @@ "setTimeout": true }, "packages": { + "@storybook/components>qs": true, "browserify>browser-resolve": true, "browserify>process": true, "eth-rpc-errors>fast-safe-stringify": true, - "nock>qs": true, "pubnub>superagent>component-emitter": true } }, @@ -4943,7 +4969,7 @@ "eth-query": { "packages": { "eth-query>json-rpc-random-id": true, - "madge>debug": true, + "nock>debug": true, "watchify>xtend": true } }, @@ -6683,7 +6709,7 @@ "globalthis>define-properties": { "packages": { "globalthis>define-properties>has-property-descriptors": true, - "nock>deep-equal>object-keys": true + "mocha>object.assign>object-keys": true } }, "globalthis>define-properties>has-property-descriptors": { @@ -6774,19 +6800,6 @@ "Intl": true } }, - "madge>debug": { - "globals": { - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "browserify>process": true, - "madge>debug>ms": true - } - }, "madge>rc>deep-extend": { "packages": { "browserify>buffer": true @@ -6822,30 +6835,17 @@ "navigator": true } }, - "nock>deep-equal": { - "packages": { - "enzyme>is-regex": true, - "enzyme>object-is": true, - "nock>deep-equal>is-arguments": true, - "nock>deep-equal>is-date-object": true, - "nock>deep-equal>object-keys": true, - "string.prototype.matchall>regexp.prototype.flags": true - } - }, - "nock>deep-equal>is-arguments": { - "packages": { - "koa>is-generator-function>has-tostringtag": true, - "string.prototype.matchall>call-bind": true - } - }, - "nock>deep-equal>is-date-object": { - "packages": { - "koa>is-generator-function>has-tostringtag": true - } - }, - "nock>qs": { + "nock>debug": { + "globals": { + "console": true, + "document": true, + "localStorage": true, + "navigator": true, + "process": true + }, "packages": { - "string.prototype.matchall>side-channel": true + "browserify>process": true, + "nock>debug>ms": true } }, "node-fetch": { diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index 8a8c07847..3613d9de2 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -288,7 +288,7 @@ "browserify>insert-module-globals>is-buffer": true, "browserify>timers-browserify": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs-mini": { @@ -388,7 +388,7 @@ "3box>ipfs>multibase": true, "browserify>assert": true, "browserify>buffer": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>dlv": { @@ -450,7 +450,7 @@ "browserify>assert": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>ipfs-bitswap>bignumber.js": { @@ -520,7 +520,7 @@ "browserify>assert": true, "browserify>browser-resolve": true, "browserify>buffer": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>ipfs-mfs>hamt-sharding": { @@ -567,7 +567,7 @@ "browserify>path-browserify": true, "browserify>timers-browserify": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>ipfs-repo>bignumber.js": { @@ -811,7 +811,7 @@ "3box>ipfs>protons": true, "base32-encode": true, "browserify>buffer": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>is-ipfs": { @@ -850,7 +850,7 @@ "browserify>insert-module-globals>is-buffer": true, "browserify>process": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -866,7 +866,7 @@ "3box>ipfs>peer-info": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p-crypto": { @@ -979,7 +979,7 @@ "browserify>events": true, "browserify>insert-module-globals>is-buffer": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "promise-to-callback": true } }, @@ -1102,7 +1102,7 @@ "browserify>assert": true, "browserify>buffer": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1161,7 +1161,7 @@ "3box>ipfs>stream-to-pull-stream": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1177,7 +1177,7 @@ "3box>ipfs>libp2p-webrtc-star>simple-peer>readable-stream": true, "browserify>buffer": true, "ethereumjs-wallet>randombytes": true, - "madge>debug": true, + "nock>debug": true, "pumpify>inherits": true } }, @@ -1377,7 +1377,7 @@ "3box>ipfs>multiaddr": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1399,7 +1399,7 @@ "browserify>buffer": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true, "uuid": true } @@ -1449,7 +1449,7 @@ "3box>ipfs>multiaddr-to-uri": true, "3box>ipfs>pull-mplex>interface-connection": true, "browserify>os-browserify": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p-websockets>pull-ws": { @@ -1478,7 +1478,7 @@ "packages": { "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor": true, "browserify>events": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor": { @@ -1518,7 +1518,7 @@ "3box>ipfs>pull-stream": true, "browserify>assert": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub": { @@ -1535,7 +1535,7 @@ "browserify>events": true, "browserify>insert-module-globals>is-buffer": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub>time-cache": { @@ -1555,7 +1555,7 @@ "3box>ipfs>libp2p-secio>pull-handshake": true, "3box>ipfs>pull-stream": true, "browserify>events": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p>libp2p-switch": { @@ -1578,7 +1578,7 @@ "browserify>assert": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1601,7 +1601,7 @@ "3box>ipfs>pull-stream": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1631,7 +1631,7 @@ "browserify>assert": true, "browserify>buffer": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1806,7 +1806,7 @@ "browserify>buffer": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>pull-mplex>interface-connection": { @@ -2218,7 +2218,7 @@ "browserify>path-browserify": true, "browserify>process": true, "depcheck>@babel/traverse": true, - "madge>debug": true, + "nock>debug": true, "nyc>convert-source-map": true } }, @@ -3263,7 +3263,7 @@ "packages": { "@metamask/eth-json-rpc-infura>@metamask/utils>superstruct": true, "eslint>fast-deep-equal": true, - "madge>debug": true + "nock>debug": true } }, "@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": { @@ -3392,15 +3392,36 @@ }, "packages": { "@babel/runtime": true, + "@metamask/eth-token-tracker>deep-equal": true, "@metamask/eth-token-tracker>eth-block-tracker": true, "@metamask/eth-token-tracker>ethjs": true, "@metamask/eth-token-tracker>human-standard-token-abi": true, "ethjs-contract": true, "ethjs-query": true, - "nock>deep-equal": true, "safe-event-emitter": true } }, + "@metamask/eth-token-tracker>deep-equal": { + "packages": { + "@metamask/eth-token-tracker>deep-equal>is-arguments": true, + "@metamask/eth-token-tracker>deep-equal>is-date-object": true, + "enzyme>is-regex": true, + "enzyme>object-is": true, + "mocha>object.assign>object-keys": true, + "string.prototype.matchall>regexp.prototype.flags": true + } + }, + "@metamask/eth-token-tracker>deep-equal>is-arguments": { + "packages": { + "koa>is-generator-function>has-tostringtag": true, + "string.prototype.matchall>call-bind": true + } + }, + "@metamask/eth-token-tracker>deep-equal>is-date-object": { + "packages": { + "koa>is-generator-function>has-tostringtag": true + } + }, "@metamask/eth-token-tracker>eth-block-tracker": { "globals": { "clearTimeout": true, @@ -4448,6 +4469,11 @@ "localStorage": true } }, + "@storybook/components>qs": { + "packages": { + "string.prototype.matchall>side-channel": true + } + }, "@storybook/react>@storybook/store>stable": { "globals": { "define": true @@ -4468,7 +4494,7 @@ "browserify>buffer": true, "browserify>util": true, "gulp-dart-sass>lodash.clonedeep": true, - "madge>debug": true, + "nock>debug": true, "semver": true } }, @@ -4691,7 +4717,7 @@ "@truffle/codec>web3-utils": true, "@truffle/decoder>@truffle/source-map-utils": true, "@truffle/decoder>bn.js": true, - "madge>debug": true + "nock>debug": true } }, "@truffle/decoder>@truffle/source-map-utils": { @@ -4701,7 +4727,7 @@ "@truffle/decoder>@truffle/source-map-utils>@truffle/code-utils": true, "@truffle/decoder>@truffle/source-map-utils>json-pointer": true, "@truffle/decoder>@truffle/source-map-utils>node-interval-tree": true, - "madge>debug": true + "nock>debug": true } }, "@truffle/decoder>@truffle/source-map-utils>@truffle/code-utils": { @@ -5240,7 +5266,7 @@ "depcheck>@babel/traverse>@babel/helper-hoist-variables": true, "depcheck>@babel/traverse>@babel/helper-split-export-declaration": true, "depcheck>@babel/traverse>globals": true, - "madge>debug": true + "nock>debug": true } }, "depcheck>@babel/traverse>@babel/helper-function-name": { @@ -5328,7 +5354,7 @@ "packages": { "eslint>fast-deep-equal": true, "eth-block-tracker>@metamask/utils>superstruct": true, - "madge>debug": true + "nock>debug": true } }, "eth-ens-namehash": { @@ -5398,7 +5424,7 @@ "packages": { "eslint>fast-deep-equal": true, "eth-json-rpc-middleware>@metamask/utils>superstruct": true, - "madge>debug": true + "nock>debug": true } }, "eth-json-rpc-middleware>eth-sig-util": { @@ -5730,10 +5756,10 @@ "setTimeout": true }, "packages": { + "@storybook/components>qs": true, "browserify>browser-resolve": true, "browserify>process": true, "eth-rpc-errors>fast-safe-stringify": true, - "nock>qs": true, "pubnub>superagent>component-emitter": true } }, @@ -5755,7 +5781,7 @@ "eth-query": { "packages": { "eth-query>json-rpc-random-id": true, - "madge>debug": true, + "nock>debug": true, "watchify>xtend": true } }, @@ -7495,7 +7521,7 @@ "globalthis>define-properties": { "packages": { "globalthis>define-properties>has-property-descriptors": true, - "nock>deep-equal>object-keys": true + "mocha>object.assign>object-keys": true } }, "globalthis>define-properties>has-property-descriptors": { @@ -7606,19 +7632,6 @@ "Intl": true } }, - "madge>debug": { - "globals": { - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "browserify>process": true, - "madge>debug>ms": true - } - }, "madge>rc>deep-extend": { "packages": { "browserify>buffer": true @@ -7654,30 +7667,17 @@ "navigator": true } }, - "nock>deep-equal": { - "packages": { - "enzyme>is-regex": true, - "enzyme>object-is": true, - "nock>deep-equal>is-arguments": true, - "nock>deep-equal>is-date-object": true, - "nock>deep-equal>object-keys": true, - "string.prototype.matchall>regexp.prototype.flags": true - } - }, - "nock>deep-equal>is-arguments": { - "packages": { - "koa>is-generator-function>has-tostringtag": true, - "string.prototype.matchall>call-bind": true - } - }, - "nock>deep-equal>is-date-object": { - "packages": { - "koa>is-generator-function>has-tostringtag": true - } - }, - "nock>qs": { + "nock>debug": { + "globals": { + "console": true, + "document": true, + "localStorage": true, + "navigator": true, + "process": true + }, "packages": { - "string.prototype.matchall>side-channel": true + "browserify>process": true, + "nock>debug>ms": true } }, "node-fetch": { diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index fc15ef26b..2e9433adf 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -288,7 +288,7 @@ "browserify>insert-module-globals>is-buffer": true, "browserify>timers-browserify": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs-mini": { @@ -388,7 +388,7 @@ "3box>ipfs>multibase": true, "browserify>assert": true, "browserify>buffer": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>dlv": { @@ -450,7 +450,7 @@ "browserify>assert": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>ipfs-bitswap>bignumber.js": { @@ -520,7 +520,7 @@ "browserify>assert": true, "browserify>browser-resolve": true, "browserify>buffer": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>ipfs-mfs>hamt-sharding": { @@ -567,7 +567,7 @@ "browserify>path-browserify": true, "browserify>timers-browserify": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>ipfs-repo>bignumber.js": { @@ -811,7 +811,7 @@ "3box>ipfs>protons": true, "base32-encode": true, "browserify>buffer": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>is-ipfs": { @@ -850,7 +850,7 @@ "browserify>insert-module-globals>is-buffer": true, "browserify>process": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -866,7 +866,7 @@ "3box>ipfs>peer-info": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p-crypto": { @@ -979,7 +979,7 @@ "browserify>events": true, "browserify>insert-module-globals>is-buffer": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "promise-to-callback": true } }, @@ -1102,7 +1102,7 @@ "browserify>assert": true, "browserify>buffer": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1161,7 +1161,7 @@ "3box>ipfs>stream-to-pull-stream": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1177,7 +1177,7 @@ "3box>ipfs>libp2p-webrtc-star>simple-peer>readable-stream": true, "browserify>buffer": true, "ethereumjs-wallet>randombytes": true, - "madge>debug": true, + "nock>debug": true, "pumpify>inherits": true } }, @@ -1377,7 +1377,7 @@ "3box>ipfs>multiaddr": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1399,7 +1399,7 @@ "browserify>buffer": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true, "uuid": true } @@ -1449,7 +1449,7 @@ "3box>ipfs>multiaddr-to-uri": true, "3box>ipfs>pull-mplex>interface-connection": true, "browserify>os-browserify": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p-websockets>pull-ws": { @@ -1478,7 +1478,7 @@ "packages": { "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor": true, "browserify>events": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor": { @@ -1518,7 +1518,7 @@ "3box>ipfs>pull-stream": true, "browserify>assert": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub": { @@ -1535,7 +1535,7 @@ "browserify>events": true, "browserify>insert-module-globals>is-buffer": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub>time-cache": { @@ -1555,7 +1555,7 @@ "3box>ipfs>libp2p-secio>pull-handshake": true, "3box>ipfs>pull-stream": true, "browserify>events": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>libp2p>libp2p-switch": { @@ -1578,7 +1578,7 @@ "browserify>assert": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1601,7 +1601,7 @@ "3box>ipfs>pull-stream": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1631,7 +1631,7 @@ "browserify>assert": true, "browserify>buffer": true, "gh-pages>async": true, - "madge>debug": true, + "nock>debug": true, "pump>once": true } }, @@ -1806,7 +1806,7 @@ "browserify>buffer": true, "browserify>events": true, "gh-pages>async": true, - "madge>debug": true + "nock>debug": true } }, "3box>ipfs>pull-mplex>interface-connection": { @@ -3102,7 +3102,7 @@ "packages": { "@metamask/eth-json-rpc-infura>@metamask/utils>superstruct": true, "eslint>fast-deep-equal": true, - "madge>debug": true + "nock>debug": true } }, "@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": { @@ -3231,15 +3231,36 @@ }, "packages": { "@babel/runtime": true, + "@metamask/eth-token-tracker>deep-equal": true, "@metamask/eth-token-tracker>eth-block-tracker": true, "@metamask/eth-token-tracker>ethjs": true, "@metamask/eth-token-tracker>human-standard-token-abi": true, "ethjs-contract": true, "ethjs-query": true, - "nock>deep-equal": true, "safe-event-emitter": true } }, + "@metamask/eth-token-tracker>deep-equal": { + "packages": { + "@metamask/eth-token-tracker>deep-equal>is-arguments": true, + "@metamask/eth-token-tracker>deep-equal>is-date-object": true, + "enzyme>is-regex": true, + "enzyme>object-is": true, + "mocha>object.assign>object-keys": true, + "string.prototype.matchall>regexp.prototype.flags": true + } + }, + "@metamask/eth-token-tracker>deep-equal>is-arguments": { + "packages": { + "koa>is-generator-function>has-tostringtag": true, + "string.prototype.matchall>call-bind": true + } + }, + "@metamask/eth-token-tracker>deep-equal>is-date-object": { + "packages": { + "koa>is-generator-function>has-tostringtag": true + } + }, "@metamask/eth-token-tracker>eth-block-tracker": { "globals": { "clearTimeout": true, @@ -3670,6 +3691,11 @@ "localStorage": true } }, + "@storybook/components>qs": { + "packages": { + "string.prototype.matchall>side-channel": true + } + }, "@storybook/react>@storybook/store>stable": { "globals": { "define": true @@ -3690,7 +3716,7 @@ "browserify>buffer": true, "browserify>util": true, "gulp-dart-sass>lodash.clonedeep": true, - "madge>debug": true, + "nock>debug": true, "semver": true } }, @@ -3913,7 +3939,7 @@ "@truffle/codec>web3-utils": true, "@truffle/decoder>@truffle/source-map-utils": true, "@truffle/decoder>bn.js": true, - "madge>debug": true + "nock>debug": true } }, "@truffle/decoder>@truffle/source-map-utils": { @@ -3923,7 +3949,7 @@ "@truffle/decoder>@truffle/source-map-utils>@truffle/code-utils": true, "@truffle/decoder>@truffle/source-map-utils>json-pointer": true, "@truffle/decoder>@truffle/source-map-utils>node-interval-tree": true, - "madge>debug": true + "nock>debug": true } }, "@truffle/decoder>@truffle/source-map-utils>@truffle/code-utils": { @@ -4516,7 +4542,7 @@ "packages": { "eslint>fast-deep-equal": true, "eth-block-tracker>@metamask/utils>superstruct": true, - "madge>debug": true + "nock>debug": true } }, "eth-ens-namehash": { @@ -4586,7 +4612,7 @@ "packages": { "eslint>fast-deep-equal": true, "eth-json-rpc-middleware>@metamask/utils>superstruct": true, - "madge>debug": true + "nock>debug": true } }, "eth-json-rpc-middleware>eth-sig-util": { @@ -4918,10 +4944,10 @@ "setTimeout": true }, "packages": { + "@storybook/components>qs": true, "browserify>browser-resolve": true, "browserify>process": true, "eth-rpc-errors>fast-safe-stringify": true, - "nock>qs": true, "pubnub>superagent>component-emitter": true } }, @@ -4943,7 +4969,7 @@ "eth-query": { "packages": { "eth-query>json-rpc-random-id": true, - "madge>debug": true, + "nock>debug": true, "watchify>xtend": true } }, @@ -6683,7 +6709,7 @@ "globalthis>define-properties": { "packages": { "globalthis>define-properties>has-property-descriptors": true, - "nock>deep-equal>object-keys": true + "mocha>object.assign>object-keys": true } }, "globalthis>define-properties>has-property-descriptors": { @@ -6774,19 +6800,6 @@ "Intl": true } }, - "madge>debug": { - "globals": { - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "browserify>process": true, - "madge>debug>ms": true - } - }, "madge>rc>deep-extend": { "packages": { "browserify>buffer": true @@ -6822,30 +6835,17 @@ "navigator": true } }, - "nock>deep-equal": { - "packages": { - "enzyme>is-regex": true, - "enzyme>object-is": true, - "nock>deep-equal>is-arguments": true, - "nock>deep-equal>is-date-object": true, - "nock>deep-equal>object-keys": true, - "string.prototype.matchall>regexp.prototype.flags": true - } - }, - "nock>deep-equal>is-arguments": { - "packages": { - "koa>is-generator-function>has-tostringtag": true, - "string.prototype.matchall>call-bind": true - } - }, - "nock>deep-equal>is-date-object": { - "packages": { - "koa>is-generator-function>has-tostringtag": true - } - }, - "nock>qs": { + "nock>debug": { + "globals": { + "console": true, + "document": true, + "localStorage": true, + "navigator": true, + "process": true + }, "packages": { - "string.prototype.matchall>side-channel": true + "browserify>process": true, + "nock>debug>ms": true } }, "node-fetch": { diff --git a/lavamoat/build-system/policy-override.json b/lavamoat/build-system/policy-override.json index 499e683e2..39640ea8d 100644 --- a/lavamoat/build-system/policy-override.json +++ b/lavamoat/build-system/policy-override.json @@ -158,7 +158,8 @@ "eslint-plugin-jest>@typescript-eslint/utils": true, "eslint>debug": true, "madge>debug": true, - "typescript": true + "typescript": true, + "nock>debug": true } }, "@typescript-eslint/eslint-plugin>@typescript-eslint/type-utils>debug": { diff --git a/lavamoat/build-system/policy.json b/lavamoat/build-system/policy.json index 2cad4ca0e..d83c594a8 100644 --- a/lavamoat/build-system/policy.json +++ b/lavamoat/build-system/policy.json @@ -52,7 +52,7 @@ "@babel/preset-typescript": true, "depcheck>@babel/traverse": true, "depcheck>json5": true, - "madge>debug": true, + "nock>debug": true, "nyc>convert-source-map": true } }, @@ -1046,6 +1046,11 @@ "pumpify>inherits": true } }, + "@metamask/eth-token-tracker>deep-equal>is-date-object": { + "packages": { + "koa>is-generator-function>has-tostringtag": true + } + }, "@metamask/jazzicon>color>color-convert": { "packages": { "@metamask/jazzicon>color>color-convert>color-name": true @@ -1076,6 +1081,11 @@ "util.deprecate": true } }, + "@storybook/components>qs": { + "packages": { + "string.prototype.matchall>side-channel": true + } + }, "@storybook/react>acorn-walk": { "globals": { "define": true @@ -1109,6 +1119,7 @@ "eslint-plugin-jest>@typescript-eslint/utils": true, "eslint>debug": true, "madge>debug": true, + "nock>debug": true, "typescript": true } }, @@ -1144,7 +1155,7 @@ "packages": { "@typescript-eslint/parser>@typescript-eslint/scope-manager": true, "@typescript-eslint/parser>@typescript-eslint/typescript-estree": true, - "madge>debug": true, + "nock>debug": true, "typescript": true } }, @@ -1177,7 +1188,7 @@ "@typescript-eslint/parser>@typescript-eslint/types": true, "eslint>is-glob": true, "globby": true, - "madge>debug": true, + "nock>debug": true, "semver": true, "typescript": true } @@ -2004,7 +2015,7 @@ "depcheck>@babel/traverse>@babel/helper-hoist-variables": true, "depcheck>@babel/traverse>@babel/helper-split-export-declaration": true, "depcheck>@babel/traverse>globals": true, - "madge>debug": true + "nock>debug": true } }, "depcheck>@babel/traverse>@babel/helper-function-name": { @@ -2176,7 +2187,7 @@ "enzyme>object.assign": { "packages": { "globalthis>define-properties": true, - "nock>deep-equal>object-keys": true, + "mocha>object.assign>object-keys": true, "string.prototype.matchall>call-bind": true, "string.prototype.matchall>has-symbols": true } @@ -2243,7 +2254,7 @@ "eslint>natural-compare": true, "eslint>regexpp": true, "globby>ignore": true, - "madge>debug": true + "nock>debug": true } }, "eslint-config-prettier": { @@ -2291,7 +2302,7 @@ "brfs>resolve": true, "eslint-plugin-import>tsconfig-paths": true, "eslint>is-glob": true, - "madge>debug": true, + "nock>debug": true, "nyc>glob": true } }, @@ -2537,7 +2548,7 @@ "eslint-plugin-jsdoc>escape-string-regexp": true, "eslint-plugin-jsdoc>spdx-expression-parse": true, "eslint>esquery": true, - "madge>debug": true, + "nock>debug": true, "semver": true } }, @@ -2764,7 +2775,7 @@ "eslint>minimatch": true, "eslint>strip-json-comments": true, "globby>ignore": true, - "madge>debug": true + "nock>debug": true } }, "eslint>@humanwhocodes/config-array": { @@ -2774,7 +2785,7 @@ "packages": { "eslint>@humanwhocodes/config-array>@humanwhocodes/object-schema": true, "eslint>minimatch": true, - "madge>debug": true + "nock>debug": true } }, "eslint>ajv": { @@ -3122,7 +3133,7 @@ "globalthis>define-properties": { "packages": { "globalthis>define-properties>has-property-descriptors": true, - "nock>deep-equal>object-keys": true + "mocha>object.assign>object-keys": true } }, "globalthis>define-properties>has-property-descriptors": { @@ -3510,10 +3521,10 @@ "console.error": true }, "packages": { + "@storybook/components>qs": true, "gulp-livereload>tiny-lr>body": true, "gulp-livereload>tiny-lr>debug": true, "gulp-livereload>tiny-lr>faye-websocket": true, - "nock>qs": true, "react>object-assign": true } }, @@ -6452,25 +6463,6 @@ "loose-envify>js-tokens": true } }, - "madge>debug": { - "builtin": { - "tty.isatty": true, - "util.deprecate": true, - "util.format": true, - "util.inspect": true - }, - "globals": { - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "madge>debug>ms": true, - "sinon>supports-color": true - } - }, "madge>detective-scss>gonzales-pe": { "globals": { "console.error": true, @@ -6498,6 +6490,13 @@ "stylelint>balanced-match": true } }, + "mocha>mkdirp": { + "builtin": { + "fs": true, + "path.dirname": true, + "path.resolve": true + } + }, "mocha>supports-color>has-flag": { "globals": { "process.argv": true @@ -6530,21 +6529,23 @@ "process.platform": true } }, - "nock>deep-equal>is-date-object": { - "packages": { - "koa>is-generator-function>has-tostringtag": true - } - }, - "nock>mkdirp": { + "nock>debug": { "builtin": { - "fs": true, - "path.dirname": true, - "path.resolve": true - } - }, - "nock>qs": { + "tty.isatty": true, + "util.deprecate": true, + "util.format": true, + "util.inspect": true + }, + "globals": { + "console": true, + "document": true, + "localStorage": true, + "navigator": true, + "process": true + }, "packages": { - "string.prototype.matchall>side-channel": true + "nock>debug>ms": true, + "sinon>supports-color": true } }, "node-sass": { @@ -6960,9 +6961,9 @@ }, "string.prototype.matchall>es-abstract>es-to-primitive": { "packages": { + "@metamask/eth-token-tracker>deep-equal>is-date-object": true, "@storybook/api>telejson>is-symbol": true, - "enzyme>is-callable": true, - "nock>deep-equal>is-date-object": true + "enzyme>is-callable": true } }, "string.prototype.matchall>get-intrinsic": { @@ -7029,7 +7030,7 @@ "globby>ignore": true, "globby>slash": true, "lodash": true, - "madge>debug": true, + "nock>debug": true, "nyc>resolve-from": true, "stylelint>@stylelint/postcss-css-in-js": true, "stylelint>@stylelint/postcss-markdown": true, @@ -7343,7 +7344,7 @@ "path.dirname": true }, "packages": { - "nock>mkdirp": true + "mocha>mkdirp": true } }, "stylelint>global-modules": { diff --git a/package.json b/package.json index 3d9fbb4c8..ec8962ecf 100644 --- a/package.json +++ b/package.json @@ -363,7 +363,7 @@ "madge": "^5.0.1", "mocha": "^7.2.0", "mockttp": "^2.6.0", - "nock": "^9.0.14", + "nock": "^13.2.9", "node-fetch": "^2.6.1", "nyc": "^15.0.0", "patch-package": "^6.4.7", diff --git a/patches/eth-query+2.1.2.patch b/patches/eth-query+2.1.2.patch index ea405d5f8..5ab82b6d5 100644 --- a/patches/eth-query+2.1.2.patch +++ b/patches/eth-query+2.1.2.patch @@ -1,5 +1,5 @@ diff --git a/node_modules/eth-query/index.js b/node_modules/eth-query/index.js -index 13e9f3c..303d703 100644 +index 13e9f3c..d714bb7 100644 --- a/node_modules/eth-query/index.js +++ b/node_modules/eth-query/index.js @@ -1,5 +1,6 @@ @@ -9,7 +9,7 @@ index 13e9f3c..303d703 100644 module.exports = EthQuery -@@ -63,7 +64,9 @@ EthQuery.prototype.submitHashrate = generateFnFor('eth_subm +@@ -63,7 +64,10 @@ EthQuery.prototype.submitHashrate = generateFnFor('eth_subm EthQuery.prototype.sendAsync = function(opts, cb){ const self = this @@ -17,6 +17,7 @@ index 13e9f3c..303d703 100644 + const payload = createPayload(opts) + debug('making request %o', payload) + self.currentProvider.sendAsync(payload, function(err, response){ ++ debug('got err = %o, response = %o', err, response) if (!err && response.error) err = new Error('EthQuery - RPC Error - '+response.error.message) if (err) return cb(err) cb(null, response.result) diff --git a/test/helpers/setup-helper.js b/test/helpers/setup-helper.js index 2c7a8299f..cb627c805 100644 --- a/test/helpers/setup-helper.js +++ b/test/helpers/setup-helper.js @@ -12,6 +12,12 @@ global.chrome = { nock.disableNetConnect(); nock.enableNetConnect('localhost'); +if (typeof beforeEach === 'function') { + /* eslint-disable-next-line jest/require-top-level-describe */ + beforeEach(() => { + nock.cleanAll(); + }); +} // catch rejections that are still unhandled when tests exit const unhandledRejections = new Map(); diff --git a/test/jest/setup.js b/test/jest/setup.js index ae49888e5..c08520920 100644 --- a/test/jest/setup.js +++ b/test/jest/setup.js @@ -1,4 +1,6 @@ // This file is for Jest-specific setup only and runs before our Jest tests. + +import nock from 'nock'; import '@testing-library/jest-dom'; jest.mock('webextension-polyfill', () => { @@ -8,3 +10,8 @@ jest.mock('webextension-polyfill', () => { }, }; }); + +/* eslint-disable-next-line jest/require-top-level-describe */ +beforeEach(() => { + nock.cleanAll(); +}); diff --git a/ui/pages/swaps/swaps.util.test.js b/ui/pages/swaps/swaps.util.test.js index d263f55c2..e1e103874 100644 --- a/ui/pages/swaps/swaps.util.test.js +++ b/ui/pages/swaps/swaps.util.test.js @@ -42,7 +42,7 @@ jest.mock('../../../shared/lib/storage-helpers', () => ({ })); describe('Swaps Util', () => { - afterAll(() => { + afterEach(() => { nock.cleanAll(); }); @@ -112,7 +112,7 @@ describe('Swaps Util', () => { }); describe('fetchTokens', () => { - beforeAll(() => { + beforeEach(() => { nock('https://swap.metaswap.codefi.network') .persist() .get('/networks/1/tokens') @@ -131,7 +131,7 @@ describe('Swaps Util', () => { }); describe('fetchAggregatorMetadata', () => { - beforeAll(() => { + beforeEach(() => { nock('https://swap.metaswap.codefi.network') .persist() .get('/networks/1/aggregatorMetadata') @@ -150,7 +150,7 @@ describe('Swaps Util', () => { }); describe('fetchTopAssets', () => { - beforeAll(() => { + beforeEach(() => { nock('https://swap.metaswap.codefi.network') .persist() .get('/networks/1/topAssets') diff --git a/yarn.lock b/yarn.lock index 32b18cf97..701ee0bff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7114,7 +7114,7 @@ assert@^2.0.0: object-is "^1.0.1" util "^0.12.0" -assertion-error@^1.0.1, assertion-error@^1.1.0: +assertion-error@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== @@ -8778,15 +8778,6 @@ chai-checkmark@^1.0.1: resolved "https://registry.yarnpkg.com/chai-checkmark/-/chai-checkmark-1.0.1.tgz#9fbb3c9ad9101f097ef288328d30f4227d74fffb" integrity sha1-n7s8mtkQHwl+8ogyjTD0In10//s= -"chai@>=1.9.2 <4.0.0": - version "3.5.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" - integrity sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc= - dependencies: - assertion-error "^1.0.1" - deep-eql "^0.1.3" - type-detect "^1.0.0" - chai@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.4.tgz#b55e655b31e1eac7099be4c08c21964fce2e6c49" @@ -10341,13 +10332,6 @@ dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= -deep-eql@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" - integrity sha1-71WKyrjeJSBs1xOQbXTlaTDrafI= - dependencies: - type-detect "0.1.1" - deep-eql@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" @@ -10355,7 +10339,7 @@ deep-eql@^3.0.1: dependencies: type-detect "^4.0.0" -deep-equal@^1.0.0, deep-equal@^1.1.0: +deep-equal@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== @@ -19241,7 +19225,7 @@ lodash.uniqby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" integrity sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI= -lodash@=3.10.1, lodash@^4.13.1, lodash@^4.16.4, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@~4.17.2: +lodash@=3.10.1, lodash@^4.13.1, lodash@^4.16.4, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -20100,7 +20084,7 @@ mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== -mkdirp@0.5.5, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.4, mkdirp@^0.5.5, mkdirp@~0.5.1: +mkdirp@0.5.5, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.4, mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -20678,20 +20662,15 @@ no-case@^3.0.3, no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" -nock@^9.0.14: - version "9.1.5" - resolved "https://registry.yarnpkg.com/nock/-/nock-9.1.5.tgz#9e4878e0e1c050bdd93ae1e326e89461ea15618b" - integrity sha512-ukkBUhGU73CmSKTpTl6N/Qjvb7Hev4rCEjgOuEBKvHmsOqz7jGh2vUXL3dPnX3ndfcmVjsFBPfKpNuJbK94SKg== +nock@^13.2.9: + version "13.2.9" + resolved "https://registry.yarnpkg.com/nock/-/nock-13.2.9.tgz#4faf6c28175d36044da4cfa68e33e5a15086ad4c" + integrity sha512-1+XfJNYF1cjGB+TKMWi29eZ0b82QOvQs2YoLNzbpWGqFMtRQHTa57osqdGj4FrFPgkO4D4AZinzUJR9VvW3QUA== dependencies: - chai ">=1.9.2 <4.0.0" - debug "^2.2.0" - deep-equal "^1.0.0" + debug "^4.1.0" json-stringify-safe "^5.0.1" - lodash "~4.17.2" - mkdirp "^0.5.0" - propagate "0.4.0" - qs "^6.5.1" - semver "^5.3.0" + lodash "^4.17.21" + propagate "^2.0.0" node-abi@^2.18.0, node-abi@^2.21.0, node-abi@^2.7.0: version "2.30.1" @@ -23126,10 +23105,10 @@ prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.6, prop-types@^15.5.7, object-assign "^4.1.1" react-is "^16.13.1" -propagate@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/propagate/-/propagate-0.4.0.tgz#f3fcca0a6fe06736a7ba572966069617c130b481" - integrity sha1-8/zKCm/gZzanulcpZgaWF8EwtIE= +propagate@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" + integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== proper-lockfile@^4.0.0: version "4.1.1" @@ -27592,21 +27571,11 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-detect@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822" - integrity sha1-C6XsKohWQORw6k6FBZcZANrFiCI= - type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5, type-detect@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-detect@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" - integrity sha1-diIXzAbbJY7EiQihKY6LlRIejqI= - type-fest@^0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934"