* Refactor event scraping and add support for scraping ERC20 approval events * Add tests for data_sources/contract-wrappers/utils
110 lines
4.8 KiB
TypeScript
110 lines
4.8 KiB
TypeScript
// tslint:disable:custom-no-magic-numbers
|
|
import * as chai from 'chai';
|
|
import { LogWithDecodedArgs } from 'ethereum-types';
|
|
import 'mocha';
|
|
|
|
import { _getEventsWithRetriesAsync } from '../../../src/data_sources/contract-wrappers/utils';
|
|
import { chaiSetup } from '../../utils/chai_setup';
|
|
|
|
chaiSetup.configure();
|
|
const expect = chai.expect;
|
|
|
|
const retryableMessage = 'network timeout: (simulated network timeout error)';
|
|
const retryableError = new Error(retryableMessage);
|
|
|
|
describe('data_sources/contract-wrappers/utils', () => {
|
|
describe('_getEventsWithRetriesAsync', () => {
|
|
it('sends a single request if it was successful', async () => {
|
|
// Pre-declare values for the fromBlock and toBlock arguments.
|
|
const expectedFromBlock = 100;
|
|
const expectedToBlock = 200;
|
|
const expectedLogs: Array<LogWithDecodedArgs<any>> = [
|
|
{
|
|
logIndex: 123,
|
|
transactionIndex: 456,
|
|
transactionHash: '0x6dd106d002873746072fc5e496dd0fb2541b68c77bcf9184ae19a42fd33657fe',
|
|
blockHash: '0x6dd106d002873746072fc5e496dd0fb2541b68c77bcf9184ae19a42fd33657ff',
|
|
blockNumber: 789,
|
|
address: '0x6dd106d002873746072fc5e496dd0fb2541b68c77bcf9184ae19a42fd3365800',
|
|
data: 'fake raw data',
|
|
topics: [],
|
|
event: 'TEST_EVENT',
|
|
args: [1, 2, 3],
|
|
},
|
|
];
|
|
|
|
// mockGetEventsAsync checks its arguments, increments `callCount`
|
|
// and returns `expectedLogs`.
|
|
let callCount = 0;
|
|
const mockGetEventsAsync = async (
|
|
fromBlock: number,
|
|
toBlock: number,
|
|
): Promise<Array<LogWithDecodedArgs<any>>> => {
|
|
expect(fromBlock).equals(expectedFromBlock);
|
|
expect(toBlock).equals(expectedToBlock);
|
|
callCount += 1;
|
|
return expectedLogs;
|
|
};
|
|
|
|
// Make sure that we get what we expected and that the mock function
|
|
// was called exactly once.
|
|
const gotLogs = await _getEventsWithRetriesAsync(mockGetEventsAsync, 3, expectedFromBlock, expectedToBlock);
|
|
expect(gotLogs).deep.equals(expectedLogs);
|
|
expect(callCount).equals(
|
|
1,
|
|
'getEventsAsync function was called more than once even though it was successful',
|
|
);
|
|
});
|
|
it('retries and eventually succeeds', async () => {
|
|
const numRetries = 5;
|
|
let callCount = 0;
|
|
// mockGetEventsAsync throws unless callCount == numRetries + 1.
|
|
const mockGetEventsAsync = async (
|
|
_fromBlock: number,
|
|
_toBlock: number,
|
|
): Promise<Array<LogWithDecodedArgs<any>>> => {
|
|
callCount += 1;
|
|
if (callCount === numRetries + 1) {
|
|
return [];
|
|
}
|
|
throw retryableError;
|
|
};
|
|
await _getEventsWithRetriesAsync(mockGetEventsAsync, numRetries, 100, 300);
|
|
expect(callCount).equals(numRetries + 1, 'getEventsAsync function was called the wrong number of times');
|
|
});
|
|
it('throws for non-retryable errors', async () => {
|
|
const numRetries = 5;
|
|
const expectedMessage = 'Non-retryable error';
|
|
// mockGetEventsAsync always throws a non-retryable error.
|
|
const mockGetEventsAsync = async (
|
|
_fromBlock: number,
|
|
_toBlock: number,
|
|
): Promise<Array<LogWithDecodedArgs<any>>> => {
|
|
throw new Error(expectedMessage);
|
|
};
|
|
// Note(albrow): This does actually return a promise (or at least a
|
|
// "promise-like object" and is a false positive in TSLint.
|
|
// tslint:disable-next-line:await-promise
|
|
await expect(_getEventsWithRetriesAsync(mockGetEventsAsync, numRetries, 100, 300)).to.be.rejectedWith(
|
|
expectedMessage,
|
|
);
|
|
});
|
|
it('throws after too many retries', async () => {
|
|
const numRetries = 5;
|
|
// mockGetEventsAsync always throws a retryable error.
|
|
const mockGetEventsAsync = async (
|
|
_fromBlock: number,
|
|
_toBlock: number,
|
|
): Promise<Array<LogWithDecodedArgs<any>>> => {
|
|
throw retryableError;
|
|
};
|
|
// Note(albrow): This does actually return a promise (or at least a
|
|
// "promise-like object" and is a false positive in TSLint.
|
|
// tslint:disable-next-line:await-promise
|
|
await expect(_getEventsWithRetriesAsync(mockGetEventsAsync, numRetries, 100, 300)).to.be.rejectedWith(
|
|
retryableMessage,
|
|
);
|
|
});
|
|
});
|
|
});
|