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

Correct and enhance documentation for subscribing to events #6129

Merged
merged 11 commits into from
Jun 1, 2023
Merged
2 changes: 2 additions & 0 deletions docs/docs/guides/web3_migration_guide/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ const web3 = new Web3();

Passing callbacks to functions is no longer supported, except for event listeners.

For that, for example, the way to subscribe and do event listening on blockchain events had changed in 4.x as you can find inside [**`web3.eth.subscribe` Migration Guide**](/docs/guides/web3_migration_guide/subscribe_migration_guide#subscribing-to-events).
Muhammad-Altabba marked this conversation as resolved.
Show resolved Hide resolved

### Not Implemented or Exported

- [extend](https://web3js.readthedocs.io/en/v1.7.3/web3.html#extend) Extending web3 modules functionality is not implemented
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,45 @@ sidebar_label: web3.eth.subscribe

## Breaking Changes

### Subscribing to events

You subscribe to blockchain events using the `web3.eth.subscribe` API.

However, in web3.js version 1.x, for example, you could subscribe to the `newBlockHeaders` event, in one step, with the following code snippet:

```typescript
var subscription = web3.eth.subscribe('newBlockHeaders', function (error, result) {
if (!error) console.log(result);
});
```

But, in web3.js Version 4.x, the function signature has changed for `web3.eth.subscribe`. In addition, the way you get notified for `data` and `error` has also changed. It is now in 2 steps: First you subscribe and then you listen to events. Here's an example of how you would subscribe to the same `newBlockHeaders` event in web3.js version 4.x:

```typescript
// in 4.x
const subscription = await web3.eth.subscribe('newHeads');

// note that in version 4.x the way you get notified for `data` and `error` has changed
subscription.on('data', async blockhead => {
console.log('New block header: ', blockhead);
});
subscription.on('error', error =>
console.log('Error when subscribing to New block header: ', error),
);
```

#### Differences

In summary, the differences you need to be aware of when subscribing to blockchain events in web3.js version 4.x are:

- The `subscribe` function signature has changed:
- It does not accept a callback function.
- It returns a subscription object that you can use to listen to `data` and `error` events.
- You should now use the `on`, or `once`, method on the newly returned subscription object to listen to `data` and `error` events, instead of passing a callback function directly.
- You can have multiple event listeners, if you have, for example multiple `on` calls. And you can get the number of listeners in you code by calling `listenerCount(event_name)` or get the listeners with `listeners(event_name)`.

Keep in mind that these differences apply to all blockchain event subscriptions, not just to the `newBlockHeaders` event.

### New Block Headers event

In 1.x, `web3.eth.subscribe('newBlockHeaders')` was used to subscribe to new block headers.
Expand All @@ -30,7 +69,18 @@ web3.eth.clearSubscriptions(function (error, success) {

// in 4.x
const subscription = await web3.eth.subscribe('newHeads');
subscription.unsubscribe().then(
console.log(), // [...] Array of subsription ids

// note that in version 4.x the way you get notified for `data` and `error` has changed
newBlocksSubscription.on('data', async blockhead => {
console.log('New block header: ', blockhead);
});
newBlocksSubscription.on('error', error =>
console.log('Error when subscribing to New block header: ', error),
);

const ids = await web3.eth.clearSubscriptions(function (error, success);
jdevcs marked this conversation as resolved.
Show resolved Hide resolved
console.log(ids); // [...] An array of subscription ids that were cleared

// note that you can unsubscribe from a specific subscription by calling unsubscribe()
// on that subscription object: `await subscription.unsubscribe();` and this would return void if succeeded.
```
2 changes: 1 addition & 1 deletion packages/web3-core/src/web3_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ export abstract class Web3Config
}

/**
* The blockHeaderTimeout is used over socket-based connections. This option defines the amount seconds it should wait for newBlockHeaders event before falling back to polling to fetch transaction receipt.
* The blockHeaderTimeout is used over socket-based connections. This option defines the amount seconds it should wait for `'newBlockHeaders'` event before falling back to polling to fetch transaction receipt.
* Default is `10` seconds.
*/
public get blockHeaderTimeout() {
Expand Down
2 changes: 1 addition & 1 deletion packages/web3-eth-contract/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export interface ContractEventOptions {
*/
fromBlock?: BlockNumberOrTag;
/**
* This allows to manually set the topics for the event filter. If given the filter property and event signature, (topic[0]) will not be set automatically. Each topic can also be a nested array of topics that behaves as “or” operation between the given nested topics.
* This allows to manually set the topics for the event filter. If given the filter property and event signature, (topic[0]) will not be set automatically. Each topic can also be a nested array of topics that behaves as `or` operation between the given nested topics.
*/
topics?: string[];
}
Expand Down
45 changes: 28 additions & 17 deletions packages/web3-eth/src/web3_eth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1244,13 +1244,13 @@ export class Web3Eth extends Web3Context<Web3EthExecutionAPI, RegisteredSubscrip
}

/**
* Gets work for miners to mine on. Returns the hash of the current block, the seedHash, and the boundary condition to be met (target).
* Gets work for miners to mine on. Returns the hash of the current block, the seedHash, and the boundary condition to be met ('target').
*
* @returns The mining work as an array of strings with the following structure:
*
* String 32 Bytes - at index 0: current block header pow-hash
* String 32 Bytes - at index 1: the seed hash used for the DAG.
* String 32 Bytes - at index 2: the boundary condition (target), 2^256 / difficulty.
* String 32 Bytes - at index 2: the boundary condition ('target'), 2^256 / difficulty.
*
* ```ts
* web3.eth.getWork().then(console.log);
Expand Down Expand Up @@ -1424,7 +1424,7 @@ export class Web3Eth extends Web3Context<Web3EthExecutionAPI, RegisteredSubscrip
/**
* @param blockCount Number of blocks in the requested range. Between `1` and `1024` blocks can be requested in a single query. Less than requested may be returned if not all blocks are available.
* @param newestBlock Highest number block of the requested range.
* @param rewardPercentiles A monotonically increasing list of percentile values to sample from each block’s effective priority fees per gas in ascending order, weighted by gas used. Example: `[“0”, “25”, “50”, “75”, “100]` or `[“0”, “0.5”, “1”, “1.5”, “3”, “80”]`
* @param rewardPercentiles A monotonically increasing list of percentile values to sample from each block’s effective priority fees per gas in ascending order, weighted by gas used. Example: `['0', '25', '50', '75', '100']` or `['0', '0.5', '1', '1.5', '3', '80']`
* @param returnFormat ({@link DataFormat} defaults to {@link DEFAULT_RETURN_FORMAT}) - Specifies how the return data from the call should be formatted.
* @returns `baseFeePerGas` and transaction effective `priorityFeePerGas` history for the requested block range if available.
* The range between `headBlock - 4` and `headBlock` is guaranteed to be available while retrieving data from the `pending` block and older history are optional to support.
Expand Down Expand Up @@ -1535,7 +1535,7 @@ export class Web3Eth extends Web3Context<Web3EthExecutionAPI, RegisteredSubscrip
}

/**
* Lets you subscribe to specific events in the blockchain.
* Let you subscribe to specific events in the blockchain.
Muhammad-Altabba marked this conversation as resolved.
Show resolved Hide resolved
*
* @param name - The subscription you want to subscribe to.
* @param args - Optional additional parameters, depending on the subscription type.
Expand All @@ -1553,22 +1553,33 @@ export class Web3Eth extends Web3Context<Web3EthExecutionAPI, RegisteredSubscrip
* - on("error") - Fires when an error in the subscription occurs.
* - on("connected") - Fires once after the subscription successfully connected. Returns the subscription id.
*
* @example
* @example **Subscribe to Smart Contract events**
* ```ts
* const subscription = web3.eth.subscribe('logs', {
* // Subscribe to `logs`
* const logSubscription = web3.eth.subscribe('logs', {
* address: '0x1234567890123456789012345678901234567890',
* topics: ['0x033456732123ffff2342342dd12342434324234234fd234fd23fd4f23d4234']
* }, function(error, result){
* if (!error)
* console.log(result);
* });
* logSubscription.on('data', (data: any) => console.log(data));
* logSubscription.on('error', (error: any) => console.log(error));
*
* const subscription = web3.eth.subscribe('logs', {
* address: '0x1234567890123456789012345678901234567890',
* topics: ['0x033456732123ffff2342342dd12342434324234234fd234fd23fd4f23d4234']
* })
* .then(logs => console.log(logs))
* .catch(error => console.log(error));
* ```
*
* @example **Subscribe to new block headers**
* ```ts
* // Subscribe to `newBlockHeaders`
* const newBlocksSubscription = await web3.eth.subscribe('newBlockHeaders');
*
* newBlocksSubscription.on('data', async blockhead => {
* console.log('New block header: ', blockhead);
*
* // You do not need the next line, if you like to keep notified for every new block
* await newBlocksSubscription.unsubscribe();
* console.log('Unsubscribed from new block headers.');
* });
* newBlocksSubscription.on('error', error =>
* console.log('Error when subscribing to New block header: ', error),
* );
* ```
*/
public async subscribe<
Expand Down Expand Up @@ -1614,11 +1625,11 @@ export class Web3Eth extends Web3Context<Web3EthExecutionAPI, RegisteredSubscrip
* Resets subscriptions.
*
* @param notClearSyncing If `true` it keeps the `syncing` subscription.
* @returns `true` if successful, otherwise `false`.
* @returns An array of subscription ids that were cleared.
*
* ```ts
* web3.eth.clearSubscriptions().then(console.log);
* > true
* > [...] An array of subscription ids that were cleared
* ```
*/
public clearSubscriptions(notClearSyncing = false): Promise<string[]> | undefined {
Expand Down
24 changes: 12 additions & 12 deletions packages/web3-eth/src/web3_subscriptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ type CommonSubscriptionEvents = {
connected: number;
};
/**
* ## subscribe(logs)
* ## subscribe('logs')
* Subscribes to incoming logs, filtered by the given options. If a valid numerical fromBlock options property is set, web3.js will retrieve logs beginning from this point, backfilling the response as necessary.
*
* You can subscribe to logs matching a given filter object, which can take the following parameters:
* - `fromBlock`: (optional, default: latest) Integer block number, or latest for the last mined block or pending”, “earliest for not yet mined transactions.
* - `fromBlock`: (optional, default: 'latest') Integer block number, or `'latest'` for the last mined block or `'pending'`, `'earliest'` for not yet mined transactions.
* - `address`: (optional) Contract address or a list of addresses from which logs should originate.
* - `topics`: (optional) Array of 32 Bytes DATA topics. Topics are order-dependent. Each topic can also be an array of DATA with “or” options.
* - `topics`: (optional) Array of 32 Bytes DATA topics. Topics are order-dependent. Each topic can also be an array of DATA with `or` options.
*
*/
export class LogsSubscription extends Web3Subscription<
Expand Down Expand Up @@ -68,13 +68,13 @@ export class LogsSubscription extends Web3Subscription<
}

/**
* ## subscribe(pendingTransactions)
* ## subscribe('pendingTransactions')
* Subscribes to incoming pending transactions.
*
* You can subscribe to pending transactions by calling web3.eth.subscribe(pendingTransactions).
* You can subscribe to pending transactions by calling web3.eth.subscribe('pendingTransactions').
* @example
* ```ts
* web3.eth.subscribe('pendingTransactions').on("data", console.log(transaction);
* (await web3.eth.subscribe('pendingTransactions')).on('data', console.log);
* ```
*/
export class NewPendingTransactionsSubscription extends Web3Subscription<
Expand All @@ -97,15 +97,15 @@ export class NewPendingTransactionsSubscription extends Web3Subscription<
}

/**
* ## subscribe(newHeads) ( same as subscribe("newBlockHeaders"))
* ## subscribe('newHeads') ( same as subscribe('newBlockHeaders'))
*
* Subscribes to incoming block headers. This can be used as timer to check for changes on the blockchain.
*
* The structure of a returned block header is {@link BlockHeaderOutput}:
* @example
* ```ts
* (await web3.eth.subscribe("newHeads")).on( // "newBlockHeaders" would work as well
* "data",
* (await web3.eth.subscribe('newHeads')).on( // 'newBlockHeaders' would work as well
* 'data',
* console.log
* );
* >{
Expand Down Expand Up @@ -145,15 +145,15 @@ export class NewHeadsSubscription extends Web3Subscription<
}

/**
* ## subscribe(syncing)
* ## subscribe('syncing')
*
* Subscribe to syncing events. This will return `true` when the node is syncing and when it’s finished syncing will return `false`, for the `changed` event.
* @example
* ```ts
* (await web3.eth.subscribe("syncing")).on("changed", console.log);
* (await web3.eth.subscribe('syncing')).on('changed', console.log);
* > `true` // when syncing
*
* (await web3.eth.subscribe("syncing")).on("data", console.log);
* (await web3.eth.subscribe('syncing')).on('data', console.log);
* > {
* startingBlock: 0,
* currentBlock: 0,
Expand Down
4 changes: 2 additions & 2 deletions packages/web3-types/src/eth_contract_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ export interface ContractInitOptions {
export interface NonPayableCallOptions {
nonce?: HexString;
/**
* The address the call `transaction` should be made from. For calls the `from` property is optional however it is
* The address which is the call (the transaction) should be made from. For calls the `from` property is optional however it is
* highly recommended to explicitly set it or it may default to address(0) depending on your node or provider.
*/
from?: Address;
/**
* The maximum gas provided for this call “transaction” (gas limit)
* The maximum gas (gas limit) provided for this call (this transaction)
*/
gas?: string;
maxPriorityFeePerGas?: HexString;
Expand Down