You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
708 lines
26 KiB
708 lines
26 KiB
/* eslint-disable jest/require-top-level-describe, jest/no-export, jest/no-identical-title */
|
|
|
|
import { fill } from 'lodash';
|
|
import {
|
|
withMockedInfuraCommunications,
|
|
withInfuraClient,
|
|
buildMockParamsWithoutBlockParamAt,
|
|
buildMockParamsWithBlockParamAt,
|
|
buildRequestWithReplacedBlockParam,
|
|
} from './helpers';
|
|
|
|
export function testsForRpcMethodNotHandledByMiddleware(
|
|
method,
|
|
{ numberOfParameters },
|
|
) {
|
|
it('attempts to pass the request off to Infura', async () => {
|
|
const request = {
|
|
method,
|
|
params: fill(Array(numberOfParameters), 'some value'),
|
|
};
|
|
const expectedResult = 'the 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.mockSuccessfulInfuraRpcCall({
|
|
request,
|
|
response: { result: expectedResult },
|
|
});
|
|
const actualResult = await withInfuraClient(({ makeRpcCall }) =>
|
|
makeRpcCall(request),
|
|
);
|
|
|
|
expect(actualResult).toStrictEqual(expectedResult);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Defines tests which exercise the behavior exhibited by an RPC method which is
|
|
* assumed to not take a block parameter. Even if it does, the value of this
|
|
* parameter will not be used in determining how to cache the method.
|
|
*
|
|
* @param method - The name of the RPC method under test.
|
|
*/
|
|
export function testsForRpcMethodAssumingNoBlockParam(method) {
|
|
it('does not hit Infura more than once for identical requests', async () => {
|
|
const requests = [{ method }, { method }];
|
|
const mockResults = ['first result', 'second 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.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[0] },
|
|
});
|
|
const results = await withInfuraClient(({ makeRpcCallsInSeries }) =>
|
|
makeRpcCallsInSeries(requests),
|
|
);
|
|
|
|
expect(results).toStrictEqual([mockResults[0], mockResults[0]]);
|
|
});
|
|
});
|
|
|
|
it('hits Infura and does not reuse the result of a previous request if the latest block number was updated since', async () => {
|
|
const requests = [{ method }, { method }];
|
|
const mockResults = ['first result', 'second result'];
|
|
|
|
await withMockedInfuraCommunications(async (comms) => {
|
|
// Note that we have to mock these requests in a specific order. The
|
|
// first block tracker request occurs because of the first RPC request.
|
|
// The second block tracker request, however, does not occur because of
|
|
// the second RPC request, but rather because we call `clock.runAll()`
|
|
// below.
|
|
comms.mockNextBlockTrackerRequest({ blockNumber: '0x1' });
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[0] },
|
|
});
|
|
comms.mockNextBlockTrackerRequest({ blockNumber: '0x2' });
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[1],
|
|
response: { result: mockResults[1] },
|
|
});
|
|
|
|
const results = await withInfuraClient(async (client) => {
|
|
const firstResult = await client.makeRpcCall(requests[0]);
|
|
// Proceed to the next iteration of the block tracker so that a new
|
|
// block is fetched and the current block is updated.
|
|
client.clock.runAll();
|
|
const secondResult = await client.makeRpcCall(requests[1]);
|
|
return [firstResult, secondResult];
|
|
});
|
|
|
|
expect(results).toStrictEqual(mockResults);
|
|
});
|
|
});
|
|
|
|
it.each([null, undefined, '\u003cnil\u003e'])(
|
|
'does not reuse the result of a previous request if it was `%s`',
|
|
async (emptyValue) => {
|
|
const requests = [{ method }, { method }];
|
|
const mockResults = [emptyValue, 'some 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.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[0] },
|
|
});
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[1],
|
|
response: { result: mockResults[1] },
|
|
});
|
|
|
|
const results = await withInfuraClient(({ makeRpcCallsInSeries }) =>
|
|
makeRpcCallsInSeries(requests),
|
|
);
|
|
|
|
expect(results).toStrictEqual(mockResults);
|
|
});
|
|
},
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Defines tests which exercise the behavior exhibited by an RPC method that
|
|
* use `blockHash` in the response data to determine whether the response is
|
|
* cacheable.
|
|
*
|
|
* @param method - The name of the RPC method under test.
|
|
*/
|
|
export function testsForRpcMethodsThatCheckForBlockHashInResponse(method) {
|
|
it('does not hit Infura more than once for identical requests and it has a valid blockHash', async () => {
|
|
const requests = [{ method }, { method }];
|
|
const mockResults = [{ blockHash: '0x100' }, { blockHash: '0x200' }];
|
|
|
|
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.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[0] },
|
|
});
|
|
|
|
const results = await withInfuraClient(({ makeRpcCallsInSeries }) =>
|
|
makeRpcCallsInSeries(requests),
|
|
);
|
|
|
|
expect(results).toStrictEqual([mockResults[0], mockResults[0]]);
|
|
});
|
|
});
|
|
|
|
it('hits Infura and does not reuse the result of a previous request if the latest block number was updated since', async () => {
|
|
const requests = [{ method }, { method }];
|
|
const mockResults = [{ blockHash: '0x100' }, { blockHash: '0x200' }];
|
|
|
|
await withMockedInfuraCommunications(async (comms) => {
|
|
// Note that we have to mock these requests in a specific order. The
|
|
// first block tracker request occurs because of the first RPC
|
|
// request. The second block tracker request, however, does not occur
|
|
// because of the second RPC request, but rather because we call
|
|
// `clock.runAll()` below.
|
|
comms.mockNextBlockTrackerRequest({ blockNumber: '0x1' });
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[0] },
|
|
});
|
|
comms.mockNextBlockTrackerRequest({ blockNumber: '0x2' });
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[1],
|
|
response: { result: mockResults[1] },
|
|
});
|
|
|
|
const results = await withInfuraClient(async (client) => {
|
|
const firstResult = await client.makeRpcCall(requests[0]);
|
|
// Proceed to the next iteration of the block tracker so that a new
|
|
// block is fetched and the current block is updated.
|
|
client.clock.runAll();
|
|
const secondResult = await client.makeRpcCall(requests[1]);
|
|
return [firstResult, secondResult];
|
|
});
|
|
|
|
expect(results).toStrictEqual(mockResults);
|
|
});
|
|
});
|
|
|
|
it.each([null, undefined, '\u003cnil\u003e'])(
|
|
'does not reuse the result of a previous request if it was `%s`',
|
|
async (emptyValue) => {
|
|
const requests = [{ method }, { method }];
|
|
const mockResults = [emptyValue, { blockHash: '0x100' }];
|
|
|
|
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.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[0] },
|
|
});
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[1],
|
|
response: { result: mockResults[1] },
|
|
});
|
|
|
|
const results = await withInfuraClient(({ makeRpcCallsInSeries }) =>
|
|
makeRpcCallsInSeries(requests),
|
|
);
|
|
|
|
expect(results).toStrictEqual(mockResults);
|
|
});
|
|
},
|
|
);
|
|
|
|
it('does not reuse the result of a previous request if result.blockHash was null', async () => {
|
|
const requests = [{ method }, { method }];
|
|
const mockResults = [
|
|
{ blockHash: null, extra: 'some value' },
|
|
{ blockHash: '0x100', extra: 'some other value' },
|
|
];
|
|
|
|
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.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[0] },
|
|
});
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[1],
|
|
response: { result: mockResults[1] },
|
|
});
|
|
|
|
const results = await withInfuraClient(({ makeRpcCallsInSeries }) =>
|
|
makeRpcCallsInSeries(requests),
|
|
);
|
|
|
|
expect(results).toStrictEqual(mockResults);
|
|
});
|
|
});
|
|
|
|
it('does not reuse the result of a previous request if result.blockHash was undefined', async () => {
|
|
const requests = [{ method }, { method }];
|
|
const mockResults = [
|
|
{ extra: 'some value' },
|
|
{ blockHash: '0x100', extra: 'some other value' },
|
|
];
|
|
|
|
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.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[0] },
|
|
});
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[1],
|
|
response: { result: mockResults[1] },
|
|
});
|
|
|
|
const results = await withInfuraClient(({ makeRpcCallsInSeries }) =>
|
|
makeRpcCallsInSeries(requests),
|
|
);
|
|
|
|
expect(results).toStrictEqual(mockResults);
|
|
});
|
|
});
|
|
|
|
it('does not reuse the result of a previous request if result.blockHash was "0x0000000000000000000000000000000000000000000000000000000000000000"', async () => {
|
|
const requests = [{ method }, { method }];
|
|
const mockResults = [
|
|
{
|
|
blockHash:
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
extra: 'some value',
|
|
},
|
|
{ blockHash: '0x100', extra: 'some other value' },
|
|
];
|
|
|
|
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.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[0] },
|
|
});
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[1],
|
|
response: { result: mockResults[1] },
|
|
});
|
|
|
|
const results = await withInfuraClient(({ makeRpcCallsInSeries }) =>
|
|
makeRpcCallsInSeries(requests),
|
|
);
|
|
|
|
expect(results).toStrictEqual(mockResults);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Defines tests which exercise the behavior exhibited by an RPC method that
|
|
* takes a block parameter. The value of this parameter can be either a block
|
|
* number or a block tag ("latest", "earliest", or "pending") and affects how
|
|
* the method is cached.
|
|
*/
|
|
/* eslint-disable-next-line jest/no-export */
|
|
export function testsForRpcMethodSupportingBlockParam(
|
|
method,
|
|
{ blockParamIndex },
|
|
) {
|
|
describe.each([
|
|
['given no block tag', 'none'],
|
|
['given a block tag of "latest"', 'latest', 'latest'],
|
|
])('%s', (_desc, blockParamType, blockParam) => {
|
|
const params =
|
|
blockParamType === 'none'
|
|
? buildMockParamsWithoutBlockParamAt(blockParamIndex)
|
|
: buildMockParamsWithBlockParamAt(blockParamIndex, blockParam);
|
|
|
|
it('does not hit Infura more than once for identical requests', async () => {
|
|
const requests = [
|
|
{ method, params },
|
|
{ method, params },
|
|
];
|
|
const mockResults = ['first result', 'second 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.mockSuccessfulInfuraRpcCall({
|
|
request: buildRequestWithReplacedBlockParam(
|
|
requests[0],
|
|
blockParamIndex,
|
|
'0x100',
|
|
),
|
|
response: { result: mockResults[0] },
|
|
});
|
|
// Note that the block-ref middleware will still allow the original
|
|
// request to go through.
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[0] },
|
|
});
|
|
|
|
const results = await withInfuraClient(({ makeRpcCallsInSeries }) =>
|
|
makeRpcCallsInSeries(requests),
|
|
);
|
|
|
|
expect(results).toStrictEqual([mockResults[0], mockResults[0]]);
|
|
});
|
|
});
|
|
|
|
it('hits Infura and does not reuse the result of a previous request if the latest block number was updated since', async () => {
|
|
const requests = [
|
|
{ method, params },
|
|
{ method, params },
|
|
];
|
|
const mockResults = ['first result', 'second result'];
|
|
|
|
await withMockedInfuraCommunications(async (comms) => {
|
|
// Note that we have to mock these requests in a specific order.
|
|
// The first block tracker request occurs because of the first RPC
|
|
// request. The second block tracker request, however, does not
|
|
// occur because of the second RPC request, but rather because we
|
|
// call `clock.runAll()` below.
|
|
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.mockSuccessfulInfuraRpcCall({
|
|
request: buildRequestWithReplacedBlockParam(
|
|
requests[0],
|
|
blockParamIndex,
|
|
'0x100',
|
|
),
|
|
response: { result: mockResults[0] },
|
|
});
|
|
// Note that the block-ref middleware will still allow the original
|
|
// request to go through.
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[0] },
|
|
});
|
|
comms.mockNextBlockTrackerRequest({ blockNumber: '0x200' });
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
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({
|
|
request: buildRequestWithReplacedBlockParam(
|
|
requests[0],
|
|
blockParamIndex,
|
|
'0x200',
|
|
),
|
|
response: { result: mockResults[1] },
|
|
});
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[1] },
|
|
});
|
|
|
|
const results = await withInfuraClient(async (client) => {
|
|
const firstResult = await client.makeRpcCall(requests[0]);
|
|
// Proceed to the next iteration of the block tracker so that a
|
|
// new block is fetched and the current block is updated.
|
|
client.clock.runAll();
|
|
const secondResult = await client.makeRpcCall(requests[1]);
|
|
return [firstResult, secondResult];
|
|
});
|
|
|
|
expect(results).toStrictEqual(mockResults);
|
|
});
|
|
});
|
|
|
|
it.each([null, undefined, '\u003cnil\u003e'])(
|
|
'does not reuse the result of a previous request if it was `%s`',
|
|
async (emptyValue) => {
|
|
const requests = [
|
|
{ method, params },
|
|
{ method, params },
|
|
];
|
|
const mockResults = [emptyValue, 'some 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.mockSuccessfulInfuraRpcCall({
|
|
request: buildRequestWithReplacedBlockParam(
|
|
requests[0],
|
|
blockParamIndex,
|
|
'0x100',
|
|
),
|
|
response: { result: mockResults[0] },
|
|
});
|
|
// Note that the block-ref middleware will still allow the original
|
|
// request to go through.
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[0] },
|
|
});
|
|
// The previous two requests will happen again, in the same order.
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: buildRequestWithReplacedBlockParam(
|
|
requests[0],
|
|
blockParamIndex,
|
|
'0x100',
|
|
),
|
|
response: { result: mockResults[1] },
|
|
});
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[1] },
|
|
});
|
|
|
|
const results = await withInfuraClient(({ makeRpcCallsInSeries }) =>
|
|
makeRpcCallsInSeries(requests),
|
|
);
|
|
|
|
expect(results).toStrictEqual(mockResults);
|
|
});
|
|
},
|
|
);
|
|
});
|
|
|
|
describe.each([
|
|
['given a block tag of "earliest"', 'earliest', 'earliest'],
|
|
['given a block number', 'block number', '0x100'],
|
|
])('%s', (_desc, blockParamType, blockParam) => {
|
|
const params = buildMockParamsWithBlockParamAt(blockParamIndex, blockParam);
|
|
|
|
it('does not hit Infura more than once for identical requests', async () => {
|
|
const requests = [
|
|
{ method, params },
|
|
{ method, params },
|
|
];
|
|
const mockResults = ['first result', 'second 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. This block number doesn't
|
|
// matter.
|
|
comms.mockNextBlockTrackerRequest();
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[0] },
|
|
});
|
|
|
|
const results = await withInfuraClient(({ makeRpcCallsInSeries }) =>
|
|
makeRpcCallsInSeries(requests),
|
|
);
|
|
|
|
expect(results).toStrictEqual([mockResults[0], mockResults[0]]);
|
|
});
|
|
});
|
|
|
|
it('reuses the result of a previous request even if the latest block number was updated since', async () => {
|
|
const requests = [
|
|
{ method, params },
|
|
{ method, params },
|
|
];
|
|
const mockResults = ['first result', 'second result'];
|
|
|
|
await withMockedInfuraCommunications(async (comms) => {
|
|
// Note that we have to mock these requests in a specific order. The
|
|
// first block tracker request occurs because of the first RPC
|
|
// request. The second block tracker request, however, does not
|
|
// occur because of the second RPC request, but rather because we
|
|
// call `clock.runAll()` below.
|
|
comms.mockNextBlockTrackerRequest({ blockNumber: '0x1' });
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[0] },
|
|
});
|
|
comms.mockNextBlockTrackerRequest({ blockNumber: '0x2' });
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[1],
|
|
response: { result: mockResults[1] },
|
|
});
|
|
|
|
const results = await withInfuraClient(async (client) => {
|
|
const firstResult = await client.makeRpcCall(requests[0]);
|
|
// Proceed to the next iteration of the block tracker so that a
|
|
// new block is fetched and the current block is updated.
|
|
client.clock.runAll();
|
|
const secondResult = await client.makeRpcCall(requests[1]);
|
|
return [firstResult, secondResult];
|
|
});
|
|
|
|
expect(results).toStrictEqual([mockResults[0], mockResults[0]]);
|
|
});
|
|
});
|
|
|
|
it.each([null, undefined, '\u003cnil\u003e'])(
|
|
'does not reuse the result of a previous request if it was `%s`',
|
|
async (emptyValue) => {
|
|
const requests = [
|
|
{ method, params },
|
|
{ method, params },
|
|
];
|
|
const mockResults = [emptyValue, 'some 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.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[0] },
|
|
});
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[1],
|
|
response: { result: mockResults[1] },
|
|
});
|
|
|
|
const results = await withInfuraClient(({ makeRpcCallsInSeries }) =>
|
|
makeRpcCallsInSeries(requests),
|
|
);
|
|
|
|
expect(results).toStrictEqual(mockResults);
|
|
});
|
|
},
|
|
);
|
|
|
|
if (blockParamType === 'earliest') {
|
|
it('treats "0x00" as a synonym for "earliest"', async () => {
|
|
const requests = [
|
|
{
|
|
method,
|
|
params: buildMockParamsWithBlockParamAt(
|
|
blockParamIndex,
|
|
blockParam,
|
|
),
|
|
},
|
|
{
|
|
method,
|
|
params: buildMockParamsWithBlockParamAt(blockParamIndex, '0x00'),
|
|
},
|
|
];
|
|
const mockResults = ['first result', 'second 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.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[0] },
|
|
});
|
|
|
|
const results = await withInfuraClient(({ makeRpcCallsInSeries }) =>
|
|
makeRpcCallsInSeries(requests),
|
|
);
|
|
|
|
expect(results).toStrictEqual([mockResults[0], mockResults[0]]);
|
|
});
|
|
});
|
|
}
|
|
|
|
if (blockParamType === 'block number') {
|
|
it('does not reuse the result of a previous request if it was made with different arguments than this one', async () => {
|
|
await withMockedInfuraCommunications(async (comms) => {
|
|
const requests = [
|
|
{
|
|
method,
|
|
params: buildMockParamsWithBlockParamAt(blockParamIndex, '0x100'),
|
|
},
|
|
{
|
|
method,
|
|
params: buildMockParamsWithBlockParamAt(blockParamIndex, '0x200'),
|
|
},
|
|
];
|
|
|
|
// 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.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: 'first result' },
|
|
});
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[1],
|
|
response: { result: 'second result' },
|
|
});
|
|
|
|
const results = await withInfuraClient(({ makeRpcCallsInSeries }) =>
|
|
makeRpcCallsInSeries(requests),
|
|
);
|
|
|
|
expect(results).toStrictEqual(['first result', 'second result']);
|
|
});
|
|
});
|
|
}
|
|
});
|
|
|
|
describe('given a block tag of "pending"', () => {
|
|
const params = buildMockParamsWithBlockParamAt(blockParamIndex, 'pending');
|
|
|
|
it('hits Infura on all calls and does not cache anything', async () => {
|
|
const requests = [
|
|
{ method, params },
|
|
{ method, params },
|
|
];
|
|
const mockResults = ['first result', 'second 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.mockSuccessfulInfuraRpcCall({
|
|
request: requests[0],
|
|
response: { result: mockResults[0] },
|
|
});
|
|
comms.mockSuccessfulInfuraRpcCall({
|
|
request: requests[1],
|
|
response: { result: mockResults[1] },
|
|
});
|
|
|
|
const results = await withInfuraClient(({ makeRpcCallsInSeries }) =>
|
|
makeRpcCallsInSeries(requests),
|
|
);
|
|
|
|
expect(results).toStrictEqual(mockResults);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|