Skip to content

Commit

Permalink
Nikos/5603/some default properties cannot set from contract class (#5756
Browse files Browse the repository at this point in the history
)

* Create getters & setters for static defaults properties

* Add web3config static variable to initialize web3Context config

* prioritize instance's value

* Update tests

* Enable optional static variables

* Keep only contractWeb3Config for static defaults

* Formatting

* Enable contract instances to listen on global config event changes

* Add tests

* Remove comment

* Fix global defaults on deployed smart contracts

* Fix clone function

* Fix defaultAccount inheritance from class level during contract deployment

* Update tests

* Update test

* Update test

* Delete unused test

* Subscribe for global config changes in contract class

* Remove static contract defaults

* Remove tests using static contract defaults

* Fix failing test

* Fix global defaults on smart contracts

* Address feedback

* Remove unused import

* fix

* Remove formatting error

* move syncWithContext in contract init options

* move syncWithContext in contract init options

* Fix and test

* Update changelog

* Update packages/web3-eth-contract/CHANGELOG.md

* Update packages/web3-eth-contract/CHANGELOG.md

* Remove comment

---------

Co-authored-by: Wyatt Barnes <me@wyatt.email>
  • Loading branch information
nikoulai and spacesailor24 authored Feb 7, 2023
1 parent ab31eb0 commit 1431e5e
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 398 deletions.
4 changes: 4 additions & 0 deletions packages/web3-eth-contract/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,10 @@ const transactionHash = receipt.transactionHash;

## [Unreleased]

### Fixed

- Fix contract defaults (#5756)

### Changed

- Update imports statements for objects that was moved between web3 packages (#5771)
Expand Down
241 changes: 39 additions & 202 deletions packages/web3-eth-contract/src/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ 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 { Web3Context, Web3EventEmitter, Web3PromiEvent } from 'web3-core';
import { Web3Context, Web3EventEmitter, Web3PromiEvent, Web3ConfigEvent } from 'web3-core';
import { ContractExecutionError, SubscriptionError, Web3ContractError } from 'web3-errors';
import {
createAccessList,
Expand Down Expand Up @@ -57,7 +57,6 @@ import {
HexString,
LogsInput,
Mutable,
Common,
} from 'web3-types';
import {
DataFormat,
Expand Down Expand Up @@ -213,69 +212,9 @@ export class Contract<Abi extends ContractAbi>
public readonly options: ContractOptions;

/**
* Can be used to set {@link Contract.defaultAccount} for all contracts.
* Set to true if you want contracts' defaults to sync with global defaults.
*/
public static defaultAccount?: HexString;

/**
* Can be used to set {@link Contract.defaultBlock} for all contracts.
*/
public static defaultBlock?: BlockNumberOrTag;

/**
* Can be used to set {@link Contract.defaultHardfork} for all contracts.
*/
public static defaultHardfork?: string;

/**
* Can be used to set {@link Contract.defaultCommon} for all contracts.
*/
public static defaultCommon?: Common;

/**
* Can be used to set {@link Contract.transactionSendTimeout} for all contracts.
*/
public static transactionSendTimeout?: number;

/**
* Can be used to set {@link Contract.transactionBlockTimeout} for all contracts.
*/
public static transactionBlockTimeout?: number;

/**
* Can be used to set {@link Contract.transactionConfirmationBlocks} for all contracts.
*/
public static transactionConfirmationBlocks?: number;

/**
* Can be used to set {@link Contract.transactionPollingInterval} for all contracts.
*/
public static transactionPollingInterval?: number;

/**
* Can be used to set {@link Contract.transactionPollingTimeout} for all contracts.
*/
public static transactionPollingTimeout?: number;

/**
* Can be used to set {@link Contract.transactionReceiptPollingInterval} for all contracts.
*/
public static transactionReceiptPollingInterval?: number;

/**
* Can be used to set {@link Contract.transactionConfirmationPollingInterval} for all contracts.
*/
public static transactionConfirmationPollingInterval?: number;

/**
* Can be used to set {@link Contract.blockHeaderTimeout} for all contracts.
*/
public static blockHeaderTimeout?: number;

/**
* Can be used to set {@link Contract.handleRevert} for all contracts.
*/
public static handleRevert?: boolean;
public syncWithContext = false;

private _errorsInterface!: AbiErrorFragment[];
private _jsonInterface!: ContractAbiWithSignature;
Expand All @@ -292,6 +231,7 @@ export class Contract<Abi extends ContractAbi>
private _methods!: ContractMethodsInterface<Abi>;
private _events!: ContractEventsInterface<Abi>;

private context?: Web3Context;
/**
* Creates a new contract instance with all its methods and events defined in its {@doclink glossary/json_interface | json interface} object.
*
Expand Down Expand Up @@ -420,6 +360,8 @@ export class Contract<Abi extends ContractAbi>
data: options?.data,
};

this.syncWithContext = (options as ContractInitOptions)?.syncWithContext ?? false;

Object.defineProperty(this.options, 'address', {
set: (value: Address) => this._parseAndSetAddress(value, returnDataFormat),
get: () => this._address,
Expand All @@ -431,131 +373,6 @@ export class Contract<Abi extends ContractAbi>
});
}

public get defaultAccount() {
return (this.constructor as typeof Contract).defaultAccount ?? super.defaultAccount;
}

public set defaultAccount(value: Address | undefined) {
super.defaultAccount = value;
}

public get defaultBlock() {
return (this.constructor as typeof Contract).defaultBlock ?? super.defaultBlock;
}

public set defaultBlock(value: BlockNumberOrTag) {
super.defaultBlock = value;
}

public get defaultHardfork() {
return (this.constructor as typeof Contract).defaultHardfork ?? super.defaultHardfork;
}

public set defaultHardfork(value: string) {
super.defaultHardfork = value;
}

public get defaultCommon(): Common | undefined {
return (this.constructor as typeof Contract).defaultCommon ?? super.defaultCommon;
}

public set defaultCommon(value: Common | undefined) {
super.defaultCommon = value;
}

public get transactionSendTimeout() {
return (
(this.constructor as typeof Contract).transactionSendTimeout ??
super.transactionSendTimeout
);
}

public set transactionSendTimeout(value: number) {
super.transactionSendTimeout = value;
}

public get transactionBlockTimeout() {
return (
(this.constructor as typeof Contract).transactionBlockTimeout ??
super.transactionBlockTimeout
);
}

public set transactionBlockTimeout(value: number) {
super.transactionBlockTimeout = value;
}

public get transactionConfirmationBlocks() {
return (
(this.constructor as typeof Contract).transactionConfirmationBlocks ??
super.transactionConfirmationBlocks
);
}

public set transactionConfirmationBlocks(value: number) {
super.transactionConfirmationBlocks = value;
}

public get transactionPollingInterval() {
return (
(this.constructor as typeof Contract).transactionPollingInterval ??
super.transactionPollingInterval
);
}

public set transactionPollingInterval(value: number) {
super.transactionPollingInterval = value;
}

public get transactionPollingTimeout() {
return (
(this.constructor as typeof Contract).transactionPollingTimeout ??
super.transactionPollingTimeout
);
}

public set transactionPollingTimeout(value: number) {
super.transactionPollingTimeout = value;
}

public get transactionReceiptPollingInterval() {
return (
(this.constructor as typeof Contract).transactionReceiptPollingInterval ??
super.transactionReceiptPollingInterval
);
}

public set transactionReceiptPollingInterval(value: number | undefined) {
super.transactionReceiptPollingInterval = value;
}

public get transactionConfirmationPollingInterval() {
return (
(this.constructor as typeof Contract).transactionConfirmationPollingInterval ??
super.transactionConfirmationPollingInterval
);
}

public set transactionConfirmationPollingInterval(value: number | undefined) {
super.transactionConfirmationPollingInterval = value;
}

public get blockHeaderTimeout() {
return (this.constructor as typeof Contract).blockHeaderTimeout ?? super.blockHeaderTimeout;
}

public set blockHeaderTimeout(value: number) {
super.blockHeaderTimeout = value;
}

public get handleRevert() {
return (this.constructor as typeof Contract).handleRevert ?? super.handleRevert;
}

public set handleRevert(value: boolean) {
super.handleRevert = value;
}

/**
* Subscribe to an event.
*
Expand Down Expand Up @@ -633,8 +450,10 @@ export class Contract<Abi extends ContractAbi>
* ```
*/
public clone() {
let newContract: Contract<any>;

if (this.options.address) {
return new Contract<Abi>(
newContract = new Contract<Abi>(
[...this._jsonInterface, ...this._errorsInterface] as unknown as Abi,
this.options.address,
{
Expand All @@ -644,23 +463,28 @@ export class Contract<Abi extends ContractAbi>
from: this.options.from,
data: this.options.data,
provider: this.currentProvider,
syncWithContext: this.syncWithContext,
},
this.getContextObject(),
);
} else {
newContract = new Contract<Abi>(
[...this._jsonInterface, ...this._errorsInterface] as unknown as Abi,
{
gas: this.options.gas,
gasPrice: this.options.gasPrice,
gasLimit: this.options.gasLimit,
from: this.options.from,
data: this.options.data,
provider: this.currentProvider,
syncWithContext: this.syncWithContext,
},
this.getContextObject(),
);
}
if (this.context) newContract.subscribeToContextEvents(this.context);

return new Contract<Abi>(
[...this._jsonInterface, ...this._errorsInterface] as unknown as Abi,
{
gas: this.options.gas,
gasPrice: this.options.gasPrice,
gasLimit: this.options.gasLimit,
from: this.options.from,
data: this.options.data,
provider: this.currentProvider,
},
this.getContextObject(),
);
return newContract;
}

/**
Expand Down Expand Up @@ -772,6 +596,7 @@ export class Contract<Abi extends ContractAbi>
// modifiedOptions.to = '0x0000000000000000000000000000000000000000';
delete modifiedOptions.to;

// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return this._contractMethodDeploySend(
abi as AbiFunctionFragment,
args as unknown[],
Expand Down Expand Up @@ -1330,4 +1155,16 @@ export class Contract<Abi extends ContractAbi>
return sub;
};
}

protected subscribeToContextEvents<T extends Web3Context>(context: T): void {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const contractThis = this;
this.context = context;

if (contractThis.syncWithContext) {
context.on(Web3ConfigEvent.CONFIG_CHANGE, event => {
contractThis.setConfig({ [event.name]: event.newValue });
});
}
}
}
4 changes: 4 additions & 0 deletions packages/web3-eth-contract/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ export interface ContractInitOptions {
readonly data?: Bytes;
readonly gasLimit?: Uint;
readonly provider?: SupportedProviders<EthExecutionAPI> | string;
/**
* If `true`, the defaults of the contract instance will be updated automatically based on the changes of the context used to instantiate the contract.
*/
readonly syncWithContext?: boolean;
}

export interface NonPayableCallOptions {
Expand Down
16 changes: 12 additions & 4 deletions packages/web3-eth-contract/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
PayableCallOptions,
ContractOptions,
Web3ContractContext,
ContractInitOptions,
} from './types';

export const getSendTxParams = ({
Expand Down Expand Up @@ -138,12 +139,19 @@ export const getEstimateGasParams = ({
return txParams as TransactionWithSenderAPI;
};

export const isContractInitOptions = (options: unknown): options is ContractOptions =>
export const isContractInitOptions = (options: unknown): options is ContractInitOptions =>
typeof options === 'object' &&
!isNullish(options) &&
['data', 'from', 'gas', 'gasPrice', 'gasLimit', 'address', 'jsonInterface'].some(
key => key in options,
);
[
'data',
'from',
'gas',
'gasPrice',
'gasLimit',
'address',
'jsonInterface',
'syncWithContext',
].some(key => key in options);

export const isWeb3ContractContext = (options: unknown): options is Web3ContractContext =>
typeof options === 'object' && !isNullish(options) && !isContractInitOptions(options);
Expand Down
Loading

0 comments on commit 1431e5e

Please sign in to comment.