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

Add events to receipt object #6410

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 23 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2007,7 +2007,6 @@ If there are any bugs, improvements, optimizations or any new feature proposal f

#### web3-eth-contract


#### web3-utils

- `soliditySha3()` with BigInt support
Expand All @@ -2021,6 +2020,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f
#### web3-eth

- Added to `Web3Config` property `contractDataInputFill` allowing users to have the choice using property `data`, `input` or `both` for contract methods to be sent to the RPC provider when creating contracts. (#6377) (#6400)
- Added `ALL_EVENTS` and `ALL_EVENTS_ABI` constants, `SendTransactionEventsBase` type, `decodeEventABI` method (#6410)

#### web3-eth-contract

Expand Down Expand Up @@ -2081,5 +2081,26 @@ If there are any bugs, improvements, optimizations or any new feature proposal f

- Dependencies updated


## [Unreleased]

### Added

#### web3-eth

- Added `ALL_EVENTS` and `ALL_EVENTS_ABI` constants, `SendTransactionEventsBase` type, `decodeEventABI` method (#6410)

#### web3-types

- Interface `EventLog` was added. (#6410)

### Fixed

#### web3-eth

- Ensure provider.supportsSubscriptions exists before watching by subscription (#6440)

### Changed

#### web3-eth-contract

- The `events` property was added to the `receipt` object (#6410)
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ describe('getEncodedEip712Data', () => {
});

it.each(erroneousTestData)('%s', (_, typedData, hashEncodedData, expectedError) => {
expect(() => getEncodedEip712Data(typedData, hashEncodedData)).toThrowError(expectedError);
expect(() => getEncodedEip712Data(typedData, hashEncodedData)).toThrow(expectedError);
});
});
6 changes: 5 additions & 1 deletion packages/web3-eth-contract/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,4 +308,8 @@ Documentation:
- Added to `Web3Config` property `contractDataInputFill` allowing users to have the choice using property `data`, `input` or `both` for contract methods to be sent to the RPC provider when creating contracts. (#6377)


## [Unreleased]
## [Unreleased]

### Changed

- The `events` property was added to the `receipt` object (#6410)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
This file is part of web3.js.

web3.js is free software: you can redistribute it and/or modify
Expand All @@ -14,13 +14,4 @@
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/>.
*/

import { AbiEventFragment } from 'web3-types';

export const ALL_EVENTS = 'ALLEVENTS';
export const ALL_EVENTS_ABI = {
name: ALL_EVENTS,
signature: '',
type: 'event',
inputs: [],
} as AbiEventFragment & { signature: string };
export { ALL_EVENTS, ALL_EVENTS_ABI } from 'web3-eth';

Check warning on line 17 in packages/web3-eth-contract/src/constant.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-eth-contract/src/constant.ts#L17

Added line #L17 was not covered by tests
31 changes: 21 additions & 10 deletions packages/web3-eth-contract/src/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@ import {
call,
estimateGas,
getLogs,
NewHeadsSubscription,
sendTransaction,
decodeEventABI,
NewHeadsSubscription,
ALL_EVENTS,
ALL_EVENTS_ABI,
SendTransactionEvents,
} from 'web3-eth';
import {
Expand Down Expand Up @@ -76,6 +79,9 @@ import {
DEFAULT_RETURN_FORMAT,
Numbers,
Web3ValidationErrorObject,
EventLog,
ContractAbiWithSignature,
ContractOptions,
} from 'web3-types';
import { format, isDataFormat, keccak256, toChecksumAddress } from 'web3-utils';
import {
Expand All @@ -85,14 +91,10 @@ import {
ValidationSchemaInput,
Web3ValidatorError,
} from 'web3-validator';
import { ALL_EVENTS, ALL_EVENTS_ABI } from './constants.js';
import { decodeEventABI, decodeMethodReturn, encodeEventABI, encodeMethodABI } from './encoding.js';
import { decodeMethodReturn, encodeEventABI, encodeMethodABI } from './encoding.js';
import { LogsSubscription } from './log_subscription.js';
import {
ContractAbiWithSignature,
ContractEventOptions,
ContractOptions,
EventLog,
NonPayableMethodObject,
NonPayableTxOptions,
PayableMethodObject,
Expand Down Expand Up @@ -707,24 +709,29 @@ export class Contract<Abi extends ContractAbi>
returnFormat?: ReturnFormat,
): Promise<(string | EventLog)[]>;
public async getPastEvents<ReturnFormat extends DataFormat = typeof DEFAULT_RETURN_FORMAT>(
eventName: keyof ContractEvents<Abi> | 'allEvents',
eventName: keyof ContractEvents<Abi> | 'allEvents' | 'ALLEVENTS',
returnFormat?: ReturnFormat,
): Promise<(string | EventLog)[]>;
public async getPastEvents<ReturnFormat extends DataFormat = typeof DEFAULT_RETURN_FORMAT>(
filter: Omit<Filter, 'address'>,
returnFormat?: ReturnFormat,
): Promise<(string | EventLog)[]>;
public async getPastEvents<ReturnFormat extends DataFormat = typeof DEFAULT_RETURN_FORMAT>(
eventName: keyof ContractEvents<Abi> | 'allEvents',
eventName: keyof ContractEvents<Abi> | 'allEvents' | 'ALLEVENTS',
filter: Omit<Filter, 'address'>,
returnFormat?: ReturnFormat,
): Promise<(string | EventLog)[]>;
public async getPastEvents<ReturnFormat extends DataFormat = typeof DEFAULT_RETURN_FORMAT>(
param1?: keyof ContractEvents<Abi> | 'allEvents' | Omit<Filter, 'address'> | ReturnFormat,
param1?:
| keyof ContractEvents<Abi>
| 'allEvents'
| 'ALLEVENTS'
| Omit<Filter, 'address'>
| ReturnFormat,
param2?: Omit<Filter, 'address'> | ReturnFormat,
param3?: ReturnFormat,
): Promise<(string | EventLog)[]> {
const eventName = typeof param1 === 'string' ? param1 : 'allEvents';
const eventName = typeof param1 === 'string' ? param1 : ALL_EVENTS;

const options =
// eslint-disable-next-line no-nested-ternary
Expand All @@ -751,11 +758,13 @@ export class Contract<Abi extends ContractAbi>
if (!abi) {
throw new Web3ContractError(`Event ${eventName} not found.`);
}

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

const logs = await getLogs(this, { fromBlock, toBlock, topics, address }, returnFormat);
const decodedLogs = logs.map(log =>
typeof log === 'string'
Expand Down Expand Up @@ -1076,6 +1085,7 @@ export class Contract<Abi extends ContractAbi>
const transactionToSend = sendTransaction(this, tx, DEFAULT_RETURN_FORMAT, {
// TODO Should make this configurable by the user
checkRevertBeforeSending: false,
contractAbi: this._jsonInterface,
});

// eslint-disable-next-line no-void
Expand Down Expand Up @@ -1117,6 +1127,7 @@ export class Contract<Abi extends ContractAbi>
newContract.options.address = receipt.contractAddress;
return newContract;
},
contractAbi: this._jsonInterface,
// TODO Should make this configurable by the user
checkRevertBeforeSending: false,
});
Expand Down
77 changes: 5 additions & 72 deletions packages/web3-eth-contract/src/encoding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,15 @@ import {
AbiConstructorFragment,
AbiEventFragment,
AbiFunctionFragment,
LogsInput,
Filter,
HexString,
Topic,
FMT_NUMBER,
FMT_BYTES,
DataFormat,
DEFAULT_RETURN_FORMAT,
ContractOptions,
} from 'web3-types';

import {
decodeLog,
decodeParameters,
encodeEventSignature,
encodeFunctionSignature,
Expand All @@ -42,12 +39,10 @@ import {
jsonInterfaceMethodToString,
} from 'web3-eth-abi';

import { blockSchema, logSchema } from 'web3-eth';

import { blockSchema, ALL_EVENTS } from 'web3-eth';
import { Web3ContractError } from 'web3-errors';

// eslint-disable-next-line import/no-cycle
import { ContractOptions, ContractAbiWithSignature, EventLog } from './types.js';
export { decodeEventABI } from 'web3-eth';

type Writeable<T> = { -readonly [P in keyof T]: T[P] };
export const encodeEventABI = (
Expand Down Expand Up @@ -77,14 +72,14 @@ export const encodeEventABI = (
} else {
opts.topics = [];
// add event signature
if (event && !event.anonymous && event.name !== 'ALLEVENTS') {
if (event && !event.anonymous && ![ALL_EVENTS, 'allEvents'].includes(event.name)) {
opts.topics.push(
event.signature ?? encodeEventSignature(jsonInterfaceMethodToString(event)),
);
}

// add event topics (indexed arguments)
if (event.name !== 'ALLEVENTS' && event.inputs) {
if (![ALL_EVENTS, 'allEvents'].includes(event.name) && event.inputs) {
for (const input of event.inputs) {
if (!input.indexed) {
continue;
Expand Down Expand Up @@ -119,68 +114,6 @@ export const encodeEventABI = (
return opts;
};

export const decodeEventABI = (
event: AbiEventFragment & { signature: string },
data: LogsInput,
jsonInterface: ContractAbiWithSignature,
returnFormat: DataFormat = DEFAULT_RETURN_FORMAT,
): EventLog => {
let modifiedEvent = { ...event };

const result = format(logSchema, data, returnFormat);

// if allEvents get the right event
if (modifiedEvent.name === 'ALLEVENTS') {
const matchedEvent = jsonInterface.find(j => j.signature === data.topics[0]);
if (matchedEvent) {
modifiedEvent = matchedEvent as AbiEventFragment & { signature: string };
} else {
modifiedEvent = { anonymous: true } as unknown as AbiEventFragment & {
signature: string;
};
}
}

// create empty inputs if none are present (e.g. anonymous events on allEvents)
modifiedEvent.inputs = modifiedEvent.inputs ?? event.inputs ?? [];

// Handle case where an event signature shadows the current ABI with non-identical
// arg indexing. If # of topics doesn't match, event is anon.
if (!modifiedEvent.anonymous) {
let indexedInputs = 0;
(modifiedEvent.inputs ?? []).forEach(input => {
if (input.indexed) {
indexedInputs += 1;
}
});

if (indexedInputs > 0 && data?.topics && data?.topics.length !== indexedInputs + 1) {
// checks if event is anonymous
modifiedEvent = {
...modifiedEvent,
anonymous: true,
inputs: [],
};
}
}

const argTopics = modifiedEvent.anonymous ? data.topics : (data.topics ?? []).slice(1);
return {
...result,
returnValues: decodeLog([...(modifiedEvent.inputs ?? [])], data.data, argTopics),
event: modifiedEvent.name,
signature:
modifiedEvent.anonymous || !data.topics || data.topics.length === 0 || !data.topics[0]
? undefined
: data.topics[0],

raw: {
data: data.data,
topics: data.topics,
},
};
};

export const encodeMethodABI = (
abi: AbiFunctionFragment | AbiConstructorFragment,
args: unknown[],
Expand Down
15 changes: 10 additions & 5 deletions packages/web3-eth-contract/src/log_subscription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@ 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/>.
*/

import { AbiEventFragment, LogsInput, HexString, Topic, DataFormat } from 'web3-types';
import {
AbiEventFragment,
LogsInput,
HexString,
Topic,
DataFormat,
EventLog,
ContractAbiWithSignature,
} from 'web3-types';
import { Web3RequestManager, Web3Subscription, Web3SubscriptionManager } from 'web3-core';
// eslint-disable-next-line import/no-cycle
import { decodeEventABI } from './encoding.js';
// eslint-disable-next-line import/no-cycle
import { EventLog, ContractAbiWithSignature } from './types.js';
import { decodeEventABI } from 'web3-eth';

/**
* LogSubscription to be used to subscribe to events logs.
Expand Down