Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getPastEvents doesn't support filter #6010

Merged
merged 13 commits into from
Apr 20, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -1375,6 +1375,7 @@ should use 4.0.1-alpha.0 for testing.
- `input` is now an acceptable property for `ContractInitOptions` in place of `data` (either can be used, but `input` is used withing the `Contract` class) (#5915)
- Added source files (#5956)
- Added hybrid build (ESM and CJS) of library (#5904)
- Added support for `getPastEvents` method to filter `allEvents` and specific event (#6010)
avkos marked this conversation as resolved.
Show resolved Hide resolved

#### web3-eth-ens

Expand Down
1 change: 1 addition & 0 deletions packages/web3-eth-contract/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ const transactionHash = receipt.transactionHash;
- `input` is now an acceptable property for `ContractInitOptions` in place of `data` (either can be used, but `input` is used withing the `Contract` class) (#5915)
- Added source files (#5956)
- Added hybrid build (ESM and CJS) of library (#5904)
- Added support for `getPastEvents` method to filter `allEvents` and specific event (#6010)

### Changed

Expand Down
28 changes: 23 additions & 5 deletions packages/web3-eth-contract/src/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import {
PayableCallOptions,
DataFormat,
DEFAULT_RETURN_FORMAT,
Numbers,
} from 'web3-types';
import { format, isDataFormat, toChecksumAddress } from 'web3-utils';
import {
Expand Down Expand Up @@ -702,7 +703,7 @@ export class Contract<Abi extends ContractAbi>
): Promise<(string | EventLog)[]> {
const eventName = typeof param1 === 'string' ? param1 : 'allEvents';

const filter =
const options =
// eslint-disable-next-line no-nested-ternary
typeof param1 !== 'string' && !isDataFormat(param1)
? param1
Expand All @@ -727,19 +728,36 @@ export class Contract<Abi extends ContractAbi>
if (!abi) {
throw new Web3ContractError(`Event ${eventName} not found.`);
}

const { fromBlock, toBlock, topics, address } = encodeEventABI(
this.options,
abi,
filter ?? {},
options ?? {},
);

const logs = await getLogs(this, { fromBlock, toBlock, topics, address }, returnFormat);
return logs.map(log =>
const decodedLogs = logs.map(log =>
typeof log === 'string'
? log
: decodeEventABI(abi, log as LogsInput, this._jsonInterface, returnFormat),
);

const filter = options?.filter ?? {};
const filterKeys = Object.keys(filter);
return eventName === 'allEvents' && filterKeys.length > 0
? decodedLogs.filter(log =>
avkos marked this conversation as resolved.
Show resolved Hide resolved
typeof log === 'string'
? true
: filterKeys.every((k: string) =>
Array.isArray(filter[k])
? (filter[k] as Numbers[]).some(
(v: Numbers) =>
String(log.returnValues[k]).toUpperCase() ===
String(v).toUpperCase(),
)
: String(log.returnValues[k]).toUpperCase() ===
String(filter[k]).toUpperCase(),
),
)
: decodedLogs;
}

private _parseAndSetAddress(value?: Address, returnFormat: DataFormat = DEFAULT_RETURN_FORMAT) {
Expand Down
40 changes: 13 additions & 27 deletions packages/web3-eth-contract/src/encoding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,9 @@ import {
AbiEventFragment,
AbiFunctionFragment,
LogsInput,
BlockNumberOrTag,
Filter,
HexString,
Topic,
Numbers,
FMT_NUMBER,
FMT_BYTES,
DataFormat,
Expand All @@ -51,27 +49,15 @@ import { Web3ContractError } from 'web3-errors';
// eslint-disable-next-line import/no-cycle
import { ContractOptions, ContractAbiWithSignature, EventLog } from './types';

type Writeable<T> = { -readonly [P in keyof T]: T[P] };
export const encodeEventABI = (
{ address }: ContractOptions,
event: AbiEventFragment & { signature: string },
options?: {
fromBlock?: BlockNumberOrTag;
toBlock?: BlockNumberOrTag;
filter?: Filter;
// Using "null" type intentionally to match specifications
// eslint-disable-next-line @typescript-eslint/ban-types
topics?: (null | Topic | Topic[])[];
},
options?: Filter,
) => {
const opts: {
filter: Filter;
fromBlock?: Numbers;
toBlock?: Numbers;
topics?: (Topic | Topic[])[];
address?: HexString;
} = {
filter: options?.filter ?? {},
};
const topics = options?.topics;
const filter = options?.filter ?? {};
const opts: Writeable<Filter> = {};

if (!isNullish(options?.fromBlock)) {
opts.fromBlock = format(blockSchema.properties.number, options?.fromBlock, {
Expand All @@ -86,11 +72,10 @@ export const encodeEventABI = (
});
}

if (options?.topics && Array.isArray(options.topics)) {
opts.topics = [...options.topics].filter(Boolean) as Topic[];
if (topics && Array.isArray(topics)) {
opts.topics = [...topics] as Topic[];
} else {
opts.topics = [];

// add event signature
if (event && !event.anonymous && event.name !== 'ALLEVENTS') {
opts.topics.push(
Expand All @@ -105,19 +90,20 @@ export const encodeEventABI = (
continue;
}

const value = opts.filter[input.name as keyof Filter];

const value = filter[input.name];
if (!value) {
// eslint-disable-next-line no-null/no-null
opts.topics.push(null);
continue;
}

// TODO: https://github.com/ethereum/web3.js/issues/344
// TODO: deal properly with components
if (Array.isArray(value)) {
opts.topics.push(...value.map(v => encodeParameter(input.type, v)));
opts.topics.push(value.map(v => encodeParameter(input.type, v)));
} else {
opts.topics.push(encodeParameter(input.type, value));
}

opts.topics.push(encodeParameter(input.type, value));
}
}
}
Expand Down
9 changes: 6 additions & 3 deletions packages/web3-eth-contract/src/log_subscription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ export class LogsSubscription extends Web3Subscription<
data: EventLog;
changed: EventLog & { removed: true };
},
{ address?: HexString; topics?: (Topic | Topic[])[]; abi: AbiEventFragment }
// eslint-disable-next-line @typescript-eslint/ban-types
{ address?: HexString; topics?: (Topic | Topic[] | null)[]; abi: AbiEventFragment }
> {
/**
* Address of tye contract
Expand All @@ -93,7 +94,8 @@ export class LogsSubscription extends Web3Subscription<
/**
* The list of topics subscribed
*/
public readonly topics?: (Topic | Topic[])[];
// eslint-disable-next-line @typescript-eslint/ban-types
public readonly topics?: (Topic | Topic[] | null)[];

/**
* The {@doclink glossary/json_interface | JSON Interface} of the event.
Expand All @@ -105,7 +107,8 @@ export class LogsSubscription extends Web3Subscription<
public constructor(
args: {
address?: HexString;
topics?: (Topic | Topic[])[];
// eslint-disable-next-line @typescript-eslint/ban-types
topics?: (Topic | Topic[] | null)[];
abi: AbiEventFragment & { signature: HexString };
jsonInterface: ContractAbiWithSignature;
},
Expand Down
Loading