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 ignoregaspricing config #7320

Merged
merged 7 commits into from
Oct 16, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions docs/docs/guides/02_web3_providers_guide/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,28 @@ await web3.eth.getBlockNumber();
// ↳ 18849658n
```

#### Websocket Providers will only terminate when closed

When connected to a WebSocket provider, the program will not automatically terminate after the code finishes running. This is to ensure the WebSocket connection remains open, allowing the program to continue listening for events.

The program will remain active until you explicitly disconnect from the WebSocket provider:

```ts
const web3 = new Web3(wsUrl);
// The program will keep running to listen for events.
```

#### Terminating the Program

When you're ready to stop the program, you can manually disconnect from the WebSocket provider by calling the disconnect method. This will properly close the connection and terminate the program:

```ts
const web3 = new Web3(wsUrl);
// When you are ready to terminate your program
web3.currentProvider?.disconnect();
// The program will now terminate
```

#### Configuring WebSocket Providers

The [`WebSocketProvider` constructor](/api/web3-providers-ws/class/WebSocketProvider#constructor) accepts two optional parameters that can be used to configure the behavior of the `WebSocketProvider`: the first parameter must be of type [`ClientRequestArgs`](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_http_d_._http_.clientrequestargs.html) or of [`ClientOptions`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e5ee5eae6a592198e469ad9f412bab8d223fcbb6/types/ws/index.d.ts#L243) and the second parameter must be of type [`ReconnectOptions`](/api/web3/namespace/utils#ReconnectOptions).
Expand Down
13 changes: 13 additions & 0 deletions docs/docs/guides/05_smart_contracts/tips_and_tricks.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ sidebar_label: 'Tips and Tricks'
📝 This article offers insights into **Smart Contracts** with helpful tips and tricks. If you have suggestions or questions, feel free to open an issue. We also welcome contributions through PRs.
:::

## Ignoring Web3.js autofill gas prices

When interacting with methods in contracts, Web3.js will automatically fill the gas. If you are using metamask or a similar provider and would rather have a suggestion elsewhere, the `ignoreGasPricing` option enables you to send transactions or interact with contracts without having web3.js automatically fill in the gas estimate.

#### Contract example

```ts
let contractDeployed: Contract<typeof BasicAbi>;
// instantiate contract...
contractDeployed.config.ignoreGasPricing = true;
const receipt = await contractDeployed.methods.setValues(1, 'string value', true).send(sendOptions);
```

## Calling Smart Contracts Methods with Parameter Overloading

### Overview of Function Overloading
Expand Down
28 changes: 28 additions & 0 deletions docs/docs/guides/09_web3_config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ There is list of configuration params that can be set for modifying behavior of
- [defaultMaxPriorityFeePerGas](/guides/web3_config/#defaultmaxpriorityfeepergas)
- [customTransactionSchema](/guides/web3_config/#customTransactionSchema)
- [defaultReturnFormat](/guides/web3_config/#defaultreturnformat)
- [ignoreGasPricing](/guides/web3_config/#ignoreGasPricing)

## Global level Config

Expand Down Expand Up @@ -477,3 +478,30 @@ export enum FMT_BYTES {
UINT8ARRAY = 'BYTES_UINT8ARRAY',
}
```

### [ignoreGasPricing]

The `ignoreGasPricing` option enables you to send transactions or interact with contracts without having web3.js automatically fill in the gas estimate. This feature is particularly useful when you prefer to let wallets or providers handle gas estimation instead.

#### Send transaction example

```ts
const web3 = new Web3(PROVIDER);
web3.config.ignoreGasPricing = true; // when setting configurations for the web3 object, this will also apply to newly created contracts from the web3 object
const transaction: TransactionWithToLocalWalletIndex = {
from: tempAcc.address,
to: '0x0000000000000000000000000000000000000000',
value: BigInt(1),
data: '0x64edfbf0e2c706ba4a09595315c45355a341a576cc17f3a19f43ac1c02f814ee',
};
const receipt = await web3.eth.sendTransaction(transaction); // web3.js will not estimate gas now.
```

#### Contract example

```ts
let contractDeployed: Contract<typeof BasicAbi>;
// instantiate contract...
contractDeployed.config.ignoreGasPricing = true;
const receipt = await contractDeployed.methods.setValues(1, 'string value', true).send(sendOptions);
```
4 changes: 4 additions & 0 deletions packages/web3-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,3 +240,7 @@ Documentation:
- Adds a new property (`customTransactionSchema`) to `Web3ConfigOptions`(#7227)

## [Unreleased]

### Added

- Added new property `ignoreGasPricing` to `Web3ConfigOptions`. If `ignoreGasPricing` is true, gasPrice will not be estimated (#7320)
15 changes: 14 additions & 1 deletion packages/web3-core/src/web3_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export interface Web3ConfigOptions {
defaultNetworkId?: Numbers;
defaultChain: string;
defaultHardfork: string;
ignoreGasPricing: boolean;

defaultCommon?: Common;
defaultTransactionType: Numbers;
Expand Down Expand Up @@ -104,6 +105,7 @@ export abstract class Web3Config
transactionTypeParser: undefined,
customTransactionSchema: undefined,
defaultReturnFormat: DEFAULT_RETURN_FORMAT,
ignoreGasPricing: false,
};

public constructor(options?: Partial<Web3ConfigOptions>) {
Expand Down Expand Up @@ -208,7 +210,7 @@ export abstract class Web3Config
* - `"latest"` - String: The latest block (current head of the blockchain)
* - `"pending"` - String: The currently mined block (including pending transactions)
* - `"finalized"` - String: (For POS networks) The finalized block is one which has been accepted as canonical by greater than 2/3 of validators
* - `"safe"` - String: (For POS networks) The safe head block is one which under normal network conditions, is expected to be included in the canonical chain. Under normal network conditions the safe head and the actual tip of the chain will be equivalent (with safe head trailing only by a few seconds). Safe heads will be less likely to be reorged than the proof of work network`s latest blocks.
* - `"safe"` - String: (For POS networks) The safe head block is one which under normal network conditions, is expected to be included in the canonical chain. Under normal network conditions the safe head and the actual tip of the chain will be equivalent (with safe head trailing only by a few seconds). Safe heads will be less likely to be reorged than the proof of work network's latest blocks.
*/
public set defaultBlock(val) {
this._triggerConfigChange('defaultBlock', val);
Expand Down Expand Up @@ -485,6 +487,17 @@ export abstract class Web3Config
this.config.defaultCommon = val;
}

/**
* Will get the ignoreGasPricing property. When true, the gasPrice, maxPriorityFeePerGas, and maxFeePerGas will not be autofilled in the transaction object.
* Useful when you want wallets to handle gas pricing.
*/
public get ignoreGasPricing() {
return this.config.ignoreGasPricing;
}
public set ignoreGasPricing(val) {
this._triggerConfigChange('ignoreGasPricing', val);
this.config.ignoreGasPricing = val;
}
public get defaultTransactionType() {
return this.config.defaultTransactionType;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ exports[`Web3Context getContextObject should return correct context object 1`] =
"useSubscriptionWhenCheckingBlockTimeout": false,
},
"handleRevert": false,
"ignoreGasPricing": false,
"maxListenersWarningThreshold": 100,
"transactionBlockTimeout": 50,
"transactionBuilder": undefined,
Expand Down
1 change: 1 addition & 0 deletions packages/web3-core/test/unit/web3_config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const defaultConfig = {
transactionBuilder: undefined,
transactionTypeParser: undefined,
customTransactionSchema: undefined,
ignoreGasPricing: false,
};
const setValue = {
string: 'newValue',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,48 @@ describe('contract', () => {
});

describe('send', () => {
it('should returns a receipt', async () => {
beforeEach(() => {
contractDeployed.config.ignoreGasPricing = false;
});
it('should return a receipt', async () => {
const receipt = await contractDeployed.methods
.setValues(1, 'string value', true)
.send(sendOptions);

expect(receipt.events).toBeUndefined();
expect(receipt).toEqual(
expect.objectContaining({
// status: BigInt(1),
transactionHash: expect.any(String),
}),
);

// To avoid issue with the `objectContaining` and `cypress` had to add
// these expectations explicitly on each attribute
expect(receipt.status).toEqual(BigInt(1));
});

it('should return a receipt with ignoring gas config true', async () => {
contractDeployed.config.ignoreGasPricing = true;
const receipt = await contractDeployed.methods
.setValues(1, 'string value', true)
.send(sendOptions);

expect(receipt.events).toBeUndefined();
expect(receipt).toEqual(
expect.objectContaining({
// status: BigInt(1),
transactionHash: expect.any(String),
}),
);

// To avoid issue with the `objectContaining` and `cypress` had to add
// these expectations explicitly on each attribute
expect(receipt.status).toEqual(BigInt(1));
});

it('should return a receipt with ignoring gas config false', async () => {
contractDeployed.config.ignoreGasPricing = false;
const receipt = await contractDeployed.methods
.setValues(1, 'string value', true)
.send(sendOptions);
Expand Down
4 changes: 4 additions & 0 deletions packages/web3-eth/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,3 +284,7 @@ Documentation:
### Changed

- Allow `getEthereumjsTxDataFrom` to return additional fields that may be passed if using a `customTransactionSchema`.

### Added

- `populateGasPrice` function now checks `Web3Context.config.ignoreGasPricing`. If `ignoreGasPricing` is true, gasPrice will not be estimated (#7320)
1 change: 1 addition & 0 deletions packages/web3-eth/src/utils/send_tx_helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ export class SendTxHelper<
}): Promise<TxType> {
let result = transactionFormatted;
if (
!this.web3Context.config.ignoreGasPricing &&
!this.options?.ignoreGasPricing &&
isNullish((transactionFormatted as Transaction).gasPrice) &&
(isNullish((transaction as Transaction).maxPriorityFeePerGas) ||
Expand Down
8 changes: 1 addition & 7 deletions packages/web3-eth/src/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,7 @@ import {
TransactionWithSenderAPI,
ETH_DATA_FORMAT,
} from 'web3-types';
import {
isAddress,
isHexStrict,
isHexString32Bytes,
isNullish,
isUInt,
} from 'web3-validator';
import { isAddress, isHexStrict, isHexString32Bytes, isNullish, isUInt } from 'web3-validator';
import {
ChainMismatchError,
HardforkMismatchError,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,34 @@ describe('Web3Eth.sendTransaction', () => {
const minedTransactionData = await web3Eth.getTransaction(response.transactionHash);
expect(minedTransactionData).toMatchObject(transaction);
});
it('should send a transaction while ignoring gas price successfully', async () => {
const transaction: TransactionWithToLocalWalletIndex = {
from: tempAcc.address,
to: '0x0000000000000000000000000000000000000000',
value: BigInt(1),
data: '0x64edfbf0e2c706ba4a09595315c45355a341a576cc17f3a19f43ac1c02f814ee',
};

const localWeb3Eth = new Web3Eth(getSystemTestProvider());
localWeb3Eth.config.ignoreGasPricing = true;
const response = await localWeb3Eth.sendTransaction(transaction);
expect(response.status).toBe(BigInt(1));
await closeOpenConnection(localWeb3Eth);
});
it('should send a transaction with automated gas price successfully', async () => {
const transaction: TransactionWithToLocalWalletIndex = {
from: tempAcc.address,
to: '0x0000000000000000000000000000000000000000',
value: BigInt(1),
data: '0x64edfbf0e2c706ba4a09595315c45355a341a576cc17f3a19f43ac1c02f814ee',
};

const localWeb3Eth = new Web3Eth(getSystemTestProvider());
localWeb3Eth.config.ignoreGasPricing = false;
const response = await localWeb3Eth.sendTransaction(transaction);
expect(response.status).toBe(BigInt(1));
await closeOpenConnection(localWeb3Eth);
});
describe('Deploy and interact with contract', () => {
let greeterContractAddress: string;

Expand Down
49 changes: 48 additions & 1 deletion packages/web3-eth/test/unit/send_tx_helper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ describe('sendTxHelper class', () => {
let sendTxHelper: SendTxHelper<DataFormat>;
let promiEvent: Web3PromiEvent<TransactionReceipt, Web3EventMap>;
let web3Context: Web3Context<EthExecutionAPI>;
beforeAll(() => {
beforeEach(() => {
jest.clearAllMocks();
web3Context = new Web3Context<EthExecutionAPI>();
promiEvent = new Web3PromiEvent<TransactionReceipt, Web3EventMap>(resolve => {
resolve({} as unknown as TransactionReceipt);
Expand Down Expand Up @@ -267,4 +268,50 @@ describe('sendTxHelper class', () => {
expect(utils.trySendTransaction).toHaveBeenCalled();
expect(wallet.signTransaction).toHaveBeenCalledWith(receipt);
});
it('should not call getTransactionGasPricing when ignoreGasPricing is true', async () => {
web3Context.config.ignoreGasPricing = true;
const transaction = {
from: '0xa7d9ddbe1f17865597fbd27ec712455208b6b76d',
input: '0x68656c6c6f21',
nonce: '0x15',
to: '0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb',
value: '0xf3dbb76162000',
type: '0x0',
chainId: '0x1',
};
const _sendTxHelper = new SendTxHelper({
web3Context,
promiEvent: promiEvent as PromiEvent,
options: {},
returnFormat: DEFAULT_RETURN_FORMAT,
});
await _sendTxHelper.populateGasPrice({
transactionFormatted: transaction,
transaction,
});
expect(getTransactionGasPricing).not.toHaveBeenCalled();
});
it('should call getTransactionGasPricing when ignoreGasPricing is false', async () => {
web3Context.config.ignoreGasPricing = false;
const transaction = {
from: '0xa7d9ddbe1f17865597fbd27ec712455208b6b76d',
input: '0x68656c6c6f21',
nonce: '0x15',
to: '0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb',
value: '0xf3dbb76162000',
type: '0x0',
chainId: '0x1',
};
const _sendTxHelper = new SendTxHelper({
web3Context,
promiEvent: promiEvent as PromiEvent,
options: {},
returnFormat: DEFAULT_RETURN_FORMAT,
});
await _sendTxHelper.populateGasPrice({
transactionFormatted: transaction,
transaction,
});
expect(getTransactionGasPricing).toHaveBeenCalled();
});
});
4 changes: 4 additions & 0 deletions packages/web3-types/src/eth_contract_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,8 @@ export interface ContractOptions {
* The max fee per gas to use for transactions.
*/
maxFeePerGas?: Uint;
/**
* Ignore gas price, turn on for metamask suggestion fee
*/
ignoreGasPricing?: boolean;
}
Loading