Skip to content

Commit

Permalink
Merge pull request #2332 from ethereum/issue/2316
Browse files Browse the repository at this point in the history
"allEvents" for contract.getPastEvents(...)
  • Loading branch information
nivida authored Feb 6, 2019
2 parents 66501d3 + e6a99be commit c8021de
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 9 deletions.
6 changes: 4 additions & 2 deletions packages/web3-eth-abi/src/AbiCoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,14 +296,16 @@ export default class AbiCoder {

const nonIndexedData = data;

const notIndexedParams = nonIndexedData ? this.decodeParameters(notIndexedInputs.filter(Boolean), nonIndexedData) : [];
const notIndexedParams = nonIndexedData
? this.decodeParameters(notIndexedInputs.filter(Boolean), nonIndexedData)
: [];

let notIndexedOffset = 0;
const returnValues = {};

inputs.forEach((res, i) => {
if (res.indexed) notIndexedOffset++;

returnValues[i] = res.type === 'string' ? '' : null;

if (!res.indexed && typeof notIndexedParams[i - notIndexedOffset] !== 'undefined') {
Expand Down
20 changes: 13 additions & 7 deletions packages/web3-eth-contract/src/AbstractContract.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,16 +159,22 @@ export default class AbstractContract extends AbstractWeb3Module {
*/
getPastEvents(eventName, options, callback) {
return new Promise(async (resolve, reject) => {
if (!this.abiModel.hasEvent(eventName)) {
reject(new Error(`Event with name "${eventName}" does not exists.`));
}
let method;

if (eventName !== 'allEvents') {
if (!this.abiModel.hasEvent(eventName)) {
reject(new Error(`Event with name "${eventName}" does not exists.`));
}

const pastEventLogsMethod = this.methodFactory.createPastEventLogsMethod(this.abiModel.getEvent(eventName));
method = this.methodFactory.createPastEventLogsMethod(this.abiModel.getEvent(eventName));
} else {
method = this.methodFactory.createAllPastEventLogsMethod(this.abiModel);
}

pastEventLogsMethod.parameters = [options];
pastEventLogsMethod.callback = callback;
method.parameters = [options];
method.callback = callback;

return resolve(await pastEventLogsMethod.execute(this));
return resolve(await method.execute(this));
});
}

Expand Down
19 changes: 19 additions & 0 deletions packages/web3-eth-contract/src/factories/MethodFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import CallContractMethod from '../methods/CallContractMethod';
import ContractDeployMethod from '../methods/ContractDeployMethod';
import PastEventLogsMethod from '../methods/PastEventLogsMethod';
import AllPastEventLogsMethod from '../methods/AllPastEventLogsMethod';
import SendContractMethod from '../methods/SendContractMethod';
import {EstimateGasMethod} from 'web3-core-method';

Expand Down Expand Up @@ -100,6 +101,24 @@ export default class MethodFactory {
);
}

/**
* Returns an object of type PastEventLogsMethod
*
* @method createPastEventLogsMethod
*
* @param {AbiModel} abiModel
*
* @returns {AllPastEventLogsMethod}
*/
createAllPastEventLogsMethod(abiModel) {
return new AllPastEventLogsMethod(
this.utils,
this.formatters,
this.contractModuleFactory.createAllEventsLogDecoder(),
abiModel
);
}

/**
* Returns an object of type CallContractMethod
*
Expand Down
56 changes: 56 additions & 0 deletions packages/web3-eth-contract/src/methods/AllPastEventLogsMethod.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
This file is part of web3.js.
web3.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
web3.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file AllPastEventLogsMethod.js
* @author Samuel Furter <samuel@ethereum.org>
* @date 2018
*/

import {GetPastLogsMethod} from 'web3-core-method';

export default class AllPastEventLogsMethod extends GetPastLogsMethod {
/**
* @param {Utils} utils
* @param {Object} formatters
* @param {AllEventsLogDecoder} eventLogDecoder
* @param {AbiModel} abiModel
*
* @constructor
*/
constructor(utils, formatters, allEventsLogDecoder, abiModel) {
super(utils, formatters);
this.abiModel = abiModel;
this.allEventsLogDecoder = allEventsLogDecoder;
}

/**
* This method will be executed after the RPC request.
*
* @method afterExecution
*
* @param {Array} response
*
* @returns {Array}
*/
afterExecution(response) {
const formattedLogs = super.afterExecution(response);

return formattedLogs.map((logItem) => {
return this.allEventsLogDecoder.decode(this.abiModel, logItem);
});
}
}
19 changes: 19 additions & 0 deletions packages/web3-eth-contract/tests/src/AbstractContractTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,25 @@ describe('AbstractContractTest', () => {
expect(getPastLogsMethodMock.callback).toBeInstanceOf(Function);
});

it('calls getPastEvents with "allEvents" and returns a resolved promise', async () => {
new GetPastLogsMethod();
const getPastLogsMethodMock = GetPastLogsMethod.mock.instances[0];

getPastLogsMethodMock.execute.mockReturnValueOnce(Promise.resolve(true));

methodFactoryMock.createAllPastEventLogsMethod.mockReturnValueOnce(getPastLogsMethodMock);

await expect(abstractContract.getPastEvents('allEvents', {}, () => {})).resolves.toEqual(true);

expect(getPastLogsMethodMock.execute).toHaveBeenCalledWith(abstractContract);

expect(methodFactoryMock.createAllPastEventLogsMethod).toHaveBeenCalledWith(abiModelMock);

expect(getPastLogsMethodMock.parameters).toEqual([{}]);

expect(getPastLogsMethodMock.callback).toBeInstanceOf(Function);
});

it('calls getPastEvents and returns a rejected promise', async () => {
abiModelMock.hasEvent.mockReturnValueOnce(false);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import CallContractMethod from '../../../src/methods/CallContractMethod';
import SendContractMethod from '../../../src/methods/SendContractMethod';
import ContractDeployMethod from '../../../src/methods/ContractDeployMethod';
import PastEventLogsMethod from '../../../src/methods/PastEventLogsMethod';
import AllPastEventLogsMethod from '../../../src/methods/AllPastEventLogsMethod';

// Mocks
jest.mock('Accounts');
Expand All @@ -23,6 +24,7 @@ jest.mock('../../../src/methods/CallContractMethod');
jest.mock('../../../src/methods/SendContractMethod');
jest.mock('../../../src/methods/ContractDeployMethod');
jest.mock('../../../src/methods/PastEventLogsMethod');
jest.mock('../../../src/methods/AllPastEventLogsMethod');

/**
* MethodFactory test
Expand Down Expand Up @@ -97,6 +99,12 @@ describe('MethodFactoryTest', () => {
expect(contractModuleFactoryMock.createEventLogDecoder).toHaveBeenCalled();
});

it('calls createAllPastEventLogsMethod and returns PastEventLogsMethod object', () => {
expect(methodFactory.createAllPastEventLogsMethod({})).toBeInstanceOf(AllPastEventLogsMethod);

expect(contractModuleFactoryMock.createAllEventsLogDecoder).toHaveBeenCalled();
});

it('calls createCallContractMethod and returns CallContractMethod object', () => {
expect(methodFactory.createCallContractMethod({})).toBeInstanceOf(CallContractMethod);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import * as Utils from 'web3-utils';
import {formatters} from 'web3-core-helpers';
import {GetPastLogsMethod} from 'web3-core-method';
import AllEventsLogDecoder from '../../../src/decoders/AllEventsLogDecoder';
import AbiModel from '../../../src/models/AbiModel';
import AllPastEventLogsMethod from '../../../src/methods/AllPastEventLogsMethod';

// Mocks
jest.mock('Utils');
jest.mock('formatters');
jest.mock('../../../src/decoders/AllEventsLogDecoder');
jest.mock('../../../src/models/AbiModel');

/**
* AllPastEventLogsMethod test
*/
describe('AllPastEventLogsMethodTest', () => {
let allPastEventLogsMethod, allEventsLogDecoderMock, abiModelMock;

beforeEach(() => {
new AllEventsLogDecoder();
allEventsLogDecoderMock = AllEventsLogDecoder.mock.instances[0];

new AbiModel();
abiModelMock = AbiModel.mock.instances[0];

allPastEventLogsMethod = new AllPastEventLogsMethod(Utils, formatters, allEventsLogDecoderMock, abiModelMock);
});

it('constructor check', () => {
expect(allPastEventLogsMethod.utils).toEqual(Utils);

expect(allPastEventLogsMethod.formatters).toEqual(formatters);

expect(allPastEventLogsMethod.allEventsLogDecoder).toEqual(allEventsLogDecoderMock);

expect(allPastEventLogsMethod.abiModel).toEqual(abiModelMock);

expect(allPastEventLogsMethod).toBeInstanceOf(GetPastLogsMethod);
});

it('calls afterExecution and returns the expected result', () => {
const response = [false, false, false];

formatters.outputLogFormatter.mockReturnValue(true);

allEventsLogDecoderMock.decode.mockReturnValue('decoded');

const mappedResponse = allPastEventLogsMethod.afterExecution(response);

expect(mappedResponse).toEqual(['decoded', 'decoded', 'decoded']);

expect(formatters.outputLogFormatter).toHaveBeenCalledTimes(3);

expect(allEventsLogDecoderMock.decode).toHaveBeenCalledTimes(3);

expect(allEventsLogDecoderMock.decode).toHaveBeenCalledWith(abiModelMock, true);
});
});

0 comments on commit c8021de

Please sign in to comment.