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

Fix and error when trying to get past events by calling contract.getPastEvents or contract.events.allEvents() if there is no matching events. #6647

Merged
6 changes: 5 additions & 1 deletion packages/web3-eth-contract/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -353,4 +353,8 @@ Documentation:

- By default, contracts will fill `data` instead of `input` within method calls (#6622)

## [Unreleased]
## [Unreleased]

### Fixed

- Fix and error that happen when trying to get past events by calling `contract.getPastEvents` or `contract.events.allEvents()`, if there is no matching events. (#6647)
3 changes: 2 additions & 1 deletion packages/web3-eth-contract/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"prettier": "^2.7.1",
"ts-jest": "^28.0.7",
"typescript": "^4.7.4",
"web3-eth-accounts": "^4.1.0"
"web3-eth-accounts": "^4.1.0",
"web3-providers-ws": "^4.0.7"
}
}
286 changes: 145 additions & 141 deletions packages/web3-eth-contract/src/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,140 +191,140 @@
};

/**
* The `web3.eth.Contract` makes it easy to interact with smart contracts on the ethereum blockchain.
* For using contract package, first install Web3 package using: `npm i web3` or `yarn add web3` based on your package manager, after that contracts features can be used as mentioned in following snippet.
* ```ts
*
* import { Web3 } from 'web3';
*
* const web3 = new Web3('https://127.0.0.1:4545');
* const abi = [...] as const; // your contract ABI
*
* let contract = new web3.eth.Contract(abi,'0xdAC17F958D2ee523a2206206994597C13D831ec7');
* await contract.methods.balanceOf('0xdAC17F958D2ee523a2206206994597C13D831ec7').call();
* ```
* For using individual package install `web3-eth-contract` and `web3-core` packages using: `npm i web3-eth-contract web3-core` or `yarn add web3-eth-contract web3-core`. This is more efficient approach for building lightweight applications.
* ```ts
*
* import { Web3Context } from 'web3-core';
* import { Contract } from 'web3-eth-contract';
*
* const abi = [...] as const; // your contract ABI
*
* let contract = new web3.eth.Contract(
* abi,
* '0xdAC17F958D2ee523a2206206994597C13D831ec7'
* new Web3Context('http://127.0.0.1:8545'));
*
* await contract.methods.balanceOf('0xdAC17F958D2ee523a2206206994597C13D831ec7').call();
* ```
* ## Generated Methods
* Following methods are generated by web3.js contract object for each of contract functions by using its ABI.
*
* ### send
* This is used to send a transaction to the smart contract and execute its method. Note this can alter the smart contract state.
*
* #### Parameters
* options?: PayableTxOptions | NonPayableTxOptions
*
* #### Returns
* [Web3PromiEvent](/api/web3/namespace/core#Web3PromiEvent) : Web3 Promi Event
*
* ```ts
* // using the promise
* myContract.methods.myMethod(123).send({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'})
* .then(function(receipt){
* // other parts of code to use receipt
* });
*
*
* // using the event emitter
* myContract.methods.myMethod(123).send({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'})
* .on('transactionHash', function(hash){
* // ...
* })
* .on('confirmation', function(confirmationNumber, receipt){
* // ...
* })
* .on('receipt', function(receipt){
* // ...
* })
* .on('error', function(error, receipt) {
* // ...
* });
*
* ```
*
* ### call
* This will execute smart contract method in the EVM without sending any transaction. Note calling cannot alter the smart contract state.
*
* #### Parameters
* options?: PayableCallOptions | NonPayableCallOptions,
* block?: BlockNumberOrTag,
*
* #### Returns
* Promise : having results of call
*
* ```ts
*
* let myContract = new web3.eth.Contract(abi, address);
*
* myContract.methods.myFunction().call()
* .then(console.log);
*
* ```
* ### estimateGas
* Returns the amount of gas consumed by executing the method in EVM without creating a new transaction on the blockchain. The returned amount can be used as a gas estimate for executing the transaction publicly. The actual gas used can be different when sending the transaction later, as the state of the smart contract can be different at that time.
*
* #### Parameters
* options?: PayableCallOptions,
* returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat,
*
* #### Returns
* Promise: The gas amount estimated.
*
* ```ts
* const estimatedGas = await contract.methods.approve('0xdAC17F958D2ee523a2206206994597C13D831ec7', 300)
* .estimateGas();
*
* ```
*
* ### encodeABI
* Encodes the ABI for this method. The resulting hex string is 32-bit function signature hash plus the passed parameters in Solidity tightly packed format. This can be used to send a transaction, call a method, or pass it into another smart contract’s method as arguments. Set the data field on web3.eth.sendTransaction options as the encodeABI() result and it is the same as calling the contract method with contract.myMethod.send().
*
* Some use cases for encodeABI() include: preparing a smart contract transaction for a multisignature wallet, working with offline wallets and cold storage and creating transaction payload for complex smart contract proxy calls.
*
* #### Parameters
* None
*
* #### Returns
* String: The encoded ABI.
*
* ```ts
* const encodedABI = await contract.methods.approve('0xdAC17F958D2ee523a2206206994597C13D831ec7', 300)
* .encodeABI();
*
* ```
*
* ### createAccessList
* This will create an access list a method execution will access when executed in the EVM.
* Note: You must specify a from address and gas if it’s not specified in options when instantiating parent contract object.
*
* #### Parameters
* options?: PayableCallOptions | NonPayableCallOptions,
* block?: BlockNumberOrTag,
*
* #### Returns
* Promise: The generated access list for transaction.
*
* ```ts
* const accessList = await contract.methods.approve('0xbEe634C21c16F05B03B704BaE071536121e6cFeA', 300)
* .createAccessList({
* from: "0x9992695e1053bb737d3cfae4743dcfc4b94f203d"
* });
* ```
*
*/
* The `web3.eth.Contract` makes it easy to interact with smart contracts on the ethereum blockchain.
* For using contract package, first install Web3 package using: `npm i web3` or `yarn add web3` based on your package manager, after that contracts features can be used as mentioned in following snippet.
* ```ts
*
* import { Web3 } from 'web3';
*
* const web3 = new Web3('https://127.0.0.1:4545');
* const abi = [...] as const; // your contract ABI
*
* let contract = new web3.eth.Contract(abi,'0xdAC17F958D2ee523a2206206994597C13D831ec7');
* await contract.methods.balanceOf('0xdAC17F958D2ee523a2206206994597C13D831ec7').call();
* ```
* For using individual package install `web3-eth-contract` and `web3-core` packages using: `npm i web3-eth-contract web3-core` or `yarn add web3-eth-contract web3-core`. This is more efficient approach for building lightweight applications.
* ```ts
*
* import { Web3Context } from 'web3-core';
* import { Contract } from 'web3-eth-contract';
*
* const abi = [...] as const; // your contract ABI
*
* let contract = new web3.eth.Contract(
* abi,
* '0xdAC17F958D2ee523a2206206994597C13D831ec7'
* new Web3Context('http://127.0.0.1:8545'));
*
* await contract.methods.balanceOf('0xdAC17F958D2ee523a2206206994597C13D831ec7').call();
* ```
* ## Generated Methods
* Following methods are generated by web3.js contract object for each of contract functions by using its ABI.
*
* ### send
* This is used to send a transaction to the smart contract and execute its method. Note this can alter the smart contract state.
*
* #### Parameters
* options?: PayableTxOptions | NonPayableTxOptions
*
* #### Returns
* [Web3PromiEvent](/api/web3/namespace/core#Web3PromiEvent) : Web3 Promi Event
*
* ```ts
* // using the promise
* myContract.methods.myMethod(123).send({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'})
* .then(function(receipt){
* // other parts of code to use receipt
* });
*
*
* // using the event emitter
* myContract.methods.myMethod(123).send({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'})
* .on('transactionHash', function(hash){
* // ...
* })
* .on('confirmation', function(confirmationNumber, receipt){
* // ...
* })
* .on('receipt', function(receipt){
* // ...
* })
* .on('error', function(error, receipt) {
* // ...
* });
*
* ```
*
* ### call
* This will execute smart contract method in the EVM without sending any transaction. Note calling cannot alter the smart contract state.
*
* #### Parameters
* options?: PayableCallOptions | NonPayableCallOptions,
* block?: BlockNumberOrTag,
*
* #### Returns
* Promise : having results of call
*
* ```ts
*
* let myContract = new web3.eth.Contract(abi, address);
*
* myContract.methods.myFunction().call()
* .then(console.log);
*
* ```
* ### estimateGas
* Returns the amount of gas consumed by executing the method in EVM without creating a new transaction on the blockchain. The returned amount can be used as a gas estimate for executing the transaction publicly. The actual gas used can be different when sending the transaction later, as the state of the smart contract can be different at that time.
*
* #### Parameters
* options?: PayableCallOptions,
* returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat,
*
* #### Returns
* Promise: The gas amount estimated.
*
* ```ts
* const estimatedGas = await contract.methods.approve('0xdAC17F958D2ee523a2206206994597C13D831ec7', 300)
* .estimateGas();
*
* ```
*
* ### encodeABI
* Encodes the ABI for this method. The resulting hex string is 32-bit function signature hash plus the passed parameters in Solidity tightly packed format. This can be used to send a transaction, call a method, or pass it into another smart contract’s method as arguments. Set the data field on web3.eth.sendTransaction options as the encodeABI() result and it is the same as calling the contract method with contract.myMethod.send().
*
* Some use cases for encodeABI() include: preparing a smart contract transaction for a multisignature wallet, working with offline wallets and cold storage and creating transaction payload for complex smart contract proxy calls.
*
* #### Parameters
* None
*
* #### Returns
* String: The encoded ABI.
*
* ```ts
* const encodedABI = await contract.methods.approve('0xdAC17F958D2ee523a2206206994597C13D831ec7', 300)
* .encodeABI();
*
* ```
*
* ### createAccessList
* This will create an access list a method execution will access when executed in the EVM.
* Note: You must specify a from address and gas if it’s not specified in options when instantiating parent contract object.
*
* #### Parameters
* options?: PayableCallOptions | NonPayableCallOptions,
* block?: BlockNumberOrTag,
*
* #### Returns
* Promise: The generated access list for transaction.
*
* ```ts
* const accessList = await contract.methods.approve('0xbEe634C21c16F05B03B704BaE071536121e6cFeA', 300)
* .createAccessList({
* from: "0x9992695e1053bb737d3cfae4743dcfc4b94f203d"
* });
* ```
*
*/
export class Contract<Abi extends ContractAbi>
extends Web3Context<EthExecutionAPI, typeof contractSubscriptions>
implements Web3EventEmitter<ContractEventEmitterInterface<Abi>>
Expand Down Expand Up @@ -538,7 +538,7 @@
if (contractContext instanceof Web3Context) {
contractContext.on(Web3ConfigEvent.CONFIG_CHANGE, event => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
this.setConfig({ [event.name]: event.newValue });

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

View check run for this annotation

Codecov / codecov/patch

packages/web3-eth-contract/src/contract.ts#L541

Added line #L541 was not covered by tests
});
}
}
Expand Down Expand Up @@ -663,7 +663,7 @@
*
* ```ts
* myContract.deploy({
* input: '0x12345...', // data keyword can be used, too.
* input: '0x12345...', // data keyword can be used, too.
* arguments: [123, 'My String']
* })
* .send({
Expand Down Expand Up @@ -898,11 +898,13 @@
);

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

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

View check run for this annotation

Codecov / codecov/patch

packages/web3-eth-contract/src/contract.ts#L904

Added line #L904 was not covered by tests
: decodeEventABI(abi, log as LogsInput, this._jsonInterface, returnFormat),
)
: [];

const filter = options?.filter ?? {};
const filterKeys = Object.keys(filter);
Expand All @@ -922,8 +924,8 @@

const inputAbi = abi.inputs?.filter(input => input.name === key)[0];
if (inputAbi?.indexed && inputAbi.type === 'string') {
const hashedIndexedString = keccak256(filter[key] as string);
if (hashedIndexedString === String(log.returnValues[key])) return true;

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

View check run for this annotation

Codecov / codecov/patch

packages/web3-eth-contract/src/contract.ts#L927-L928

Added lines #L927 - L928 were not covered by tests
}

return (
Expand Down Expand Up @@ -1159,7 +1161,7 @@
} catch (error: unknown) {
if (error instanceof ContractExecutionError) {
// this will parse the error data by trying to decode the ABI error inputs according to EIP-838
decodeContractErrorData(errorsAbi, error.cause);

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

View check run for this annotation

Codecov / codecov/patch

packages/web3-eth-contract/src/contract.ts#L1164

Added line #L1164 was not covered by tests
}
throw error;
}
Expand Down Expand Up @@ -1189,7 +1191,7 @@
} catch (error: unknown) {
if (error instanceof ContractExecutionError) {
// this will parse the error data by trying to decode the ABI error inputs according to EIP-838
decodeContractErrorData(errorsAbi, error.cause);

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

View check run for this annotation

Codecov / codecov/patch

packages/web3-eth-contract/src/contract.ts#L1194

Added line #L1194 was not covered by tests
}
throw error;
}
Expand Down Expand Up @@ -1225,7 +1227,7 @@
void transactionToSend.on('error', (error: unknown) => {
if (error instanceof ContractExecutionError) {
// this will parse the error data by trying to decode the ABI error inputs according to EIP-838
decodeContractErrorData(errorsAbi, error.cause);

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

View check run for this annotation

Codecov / codecov/patch

packages/web3-eth-contract/src/contract.ts#L1230

Added line #L1230 was not covered by tests
}
});
return transactionToSend;
Expand Down Expand Up @@ -1322,7 +1324,9 @@
// emit past events when fromBlock is defined
this.getPastEvents(abi.name, { fromBlock, topics }, returnFormat)
.then(logs => {
logs.forEach(log => sub.emit('data', log as EventLog));
if (logs) {
logs.forEach(log => sub.emit('data', log as EventLog));
}
})
.catch((error: Error) => {
sub.emit(
Expand Down
Loading
Loading