How to Subscribe to Mined Transactions via WebSocket Endpoints

Learn how to subscribe to mined transactions via WebSockets, and view the full transactions objects or hashes mined on the network based on specified filters and block tags.

This tutorial uses the alchemy_minedTransactions subscription endpoint.

Alchemy provides the most effective method to subscribe to mined transactions, log events, and new blocks using WebSockets on Ethereum, Polygon, Arbitrum, and Optimism. You can access direct subscription types by connecting to WebSocket endpoints using modern Web3 libraries.

In this tutorial, we will test and create a sample project using the alchemy_minedTransactions method with Viem and Ethers.js.

What relevance does the alchemy_minedTransactions provide to users?

  • Tracking transactions being mined and notify users via SMS - Alchemy Notify API
  • Display all transactions within the Ethereum network on a rolling basis

How does alchemy_minedTransactions compare to [alchemy_pendingTransactions](ref:alchemy-pendingTransactions)? Although both these Subscription API endpoints emit full transaction objects or hashes and filter based on specified parameters, they serve two different objectives. The alchemy_minedTransactions returns entire transactions that are mined on the network whereas alchemy_pendingTransactions returns transactions that are sent to the network and marked as pending.

Developers can enhance the requests with specific parameters including:

  • addresses(optional): Singular address or array of addresses to receive pending transactions sent from this address.
  • includeRemoved(optional): Singular address or array of addresses from receive pending transactions sent from this address.
  • hashesOnly(optional - default set to false): The response matches the payload of eth_getTransactionByHash. This is information about a transaction by the transaction hash including blockHash, blockNumber and transactionIndex. If set to true, the payload will return only the hashes of the mined transactions.

Step 0: Configure your developer environment

Before you begin, complete the following steps to set up your web3 developer environment.

1. Install Node.js (> 14) on your local machine

2. Install npm on your local machine

3. Install wscat on your local machine

To check your Node version, run the following command in your terminal:

bash
$node -v

4. Create a free Alchemy account

Step 1: Open your Alchemy App

Once your Alchemy account is created, there will also be a default app that is also created.

To create another Alchemy app, check out this video.

Step 2: Get WebSocket URL from Alchemy App

Once you have created your app, get your WebSocket URL that we will use later in this tutorial.

  1. Click on your app’s View Key button in the dashboard
  2. Copy and save the WebSocket URL

Step 3: Output Mined Transactions Using wscat

Wscat is a terminal or shell tool used to connect to the WebSockets server. Each Alchemy application will provide a WebSocket URL that can be used directly with the wscat command.

  1. Initiate the WebSocket stream
  2. Enter the specific call command

The following example will use the demo key, but should be replaced with your key from Step 2.

From your terminal, run the following commands:

wscat
$// initiate websocket stream first and replace demo with your key
>wscat -c wss://eth-mainnet.alchemyapi.io/v2/demo
>
>// no param specification - return all mined txs
>{"jsonrpc":"2.0","id": 2, "method": "eth_subscribe", "params": ["alchemy_minedTransactions"]}
>
>// to and from filters, hashesOnly = true
>{"jsonrpc": "2.0", "method": "eth_subscribe","params": ["alchemy_minedTransactions", {"addresses": [{"to": "0x9f3ce0ad29b767d809642a53c2bccc9a130659d7", "from": "0x228f108fd09450d083bb33fe0cc50ae449bc7e11"}, {"to": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"}],"includeRemoved": false, "hashesOnly": true}],"id": 1}

If successful, you should see output that looks something like this:

Results
1{"id":1,"result":"0xf13f7073ddef66a8c1b0c9c9f0e543c3","jsonrpc":"2.0"}
2
3// hashesOnly = true
4{
5 "jsonrpc": "2.0",
6 "method": "eth_subscription",
7 "params": {
8 "result": {
9 "removed": false
10 "transaction": {
11 "hash":"0xa8f2cf69e302da6c8100b80298ed77c37b6e75eed1177ca22acd5772c9fb9876",
12 }
13 },
14 "subscription": "0xf13f7073ddef66a8c1b0c9c9f0e543c3"
15 }
16}
17
18// hashesOnly = false
19{
20 "jsonrpc": "2.0",
21 "method": "eth_subscription",
22 "params": {
23 "result": {
24 "removed": false
25 "transaction": {
26 "blockHash":"0xbe847be2bceb74e660daf96b3f0669d58f59dc9101715689a00ef864a5408f43",
27 "blockNumber":"0x5b8d80",
28 "hash":"0xa8f2cf69e302da6c8100b80298ed77c37b6e75eed1177ca22acd5772c9fb9876",
29 "from":"0x2a9847093ad514639e8cdec960b5e51686960291",
30 "gas":"0x4f588",
31 "gasPrice":"0xc22a75840",
32 "input":"0x000101d521928b4146",
33 "nonce":"0x9a2",
34 "r":"0xb5889c55a0ebbf86627524affc9c4fdedc4608bee7a0f9880b5ec965d58e4264",
35 "s":"0x2da32e817e2483ec2199ec0121b93384ac820049a75e11b40d152fc7558a5d72",
36 "to":"0xc7ed8919c70dd8ccf1a57c0ed75b25ceb2dd22d1",
37 "transactionIndex":"0x14",
38 "type":"0x0",
39 "v":"0x1c",
40 "value":"0x0"
41 }
42 },
43 "subscription": "0xf13f7073ddef66a8c1b0c9c9f0e543c3"
44 }
45}

By using wscat, you are able to verify the transaction immediately via the computer’s terminal or shell.

Step 4: Create a Node project

Let’s create an empty repository and install the necessary dependencies for WebSocket connections. We can use either Viem or Ethers.js to manage WebSocket subscriptions.

From your terminal, run the following commands:

$mkdir mined-transactions && cd mined-transactions
>npm init -y
>npm install viem
>touch main.js

This will create a repository named mined-transactions that holds all the files and dependencies we need.

Open this repo in your preferred code editor, where we’ll write our code in the main.js file.

Step 5: Output Mined Transactions using WebSocket libraries

Next, we’ll demonstrate how to use Viem or Ethers.js to subscribe to mined transactions.

To make requests using Alchemy’s minedTransactions API, we recommend reviewing the alchemy_minedTransactions docs.

Next, add the following code to the main.js file, using your Alchemy API key:

1import { createPublicClient, webSocket } from 'viem'
2import { mainnet } from 'viem/chains'
3
4const client = createPublicClient({
5 chain: mainnet,
6 transport: webSocket('wss://eth-mainnet.g.alchemy.com/v2/<-- ALCHEMY APP API KEY -->')
7})
8
9// Subscribe to new blocks to get mined transactions
10const unsubscribe = client.watchBlocks({
11 onBlock: async (block) => {
12 console.log('New block:', block.number)
13
14 // Get all transactions in the block
15 const blockWithTxs = await client.getBlock({
16 blockNumber: block.number,
17 includeTransactions: true
18 })
19
20 console.log(`Block ${block.number} has ${blockWithTxs.transactions.length} transactions`)
21 blockWithTxs.transactions.forEach((tx, index) => {
22 if (index < 3) { // Show first 3 transactions for brevity
23 console.log('Mined transaction:', tx.hash)
24 }
25 })
26 }
27})
28
29console.log('Listening for mined transactions...')

Run this script by running the following command in your terminal:

node main.js

It should look something like this:

If successful, you should see a stream of transactions as the result. This stream of output indicates the all transactions that are mined on the Ethereum Mainnet.

Results
1{
2 removed: false,
3 transaction: {
4 blockHash: '0x1a6adfef39de127f52cd451af2352a97c06cccdd6afe3a30bfa26c45165de74d',
5 blockNumber: '0xf25e13',
6 from: '0x30d762b88f9e4cd6aca5ee47da31538d3d02ebae',
7 gas: '0x5208',
8 gasPrice: '0x4486199b4',
9 hash: '0x2a35069462e8ff5ae44579cce690116b0520e2c190fa75a452b50190bfec862c',
10 input: '0x',
11 nonce: '0x4',
12 to: '0x974caa59e49682cda0ad2bbe82983419a2ecc400',
13 transactionIndex: '0xae',
14 value: '0x32e997e5e977820',
15 type: '0x0',
16 chainId: '0x1',
17 v: '0x25',
18 r: '0x89b952803c6e94e4caaaaa3c82d426d40fdc5471019a9ff550fc006a546a8537',
19 s: '0x1d5180386250c53f7073a06d2dd02790a410e03cf1d8184cc861456bdefb2325'
20 }
21}
22{
23 removed: false,
24 transaction: {
25 blockHash: '0x1a6adfef39de127f52cd451af2352a97c06cccdd6afe3a30bfa26c45165de74d',
26 blockNumber: '0xf25e13',
27 from: '0xaccbbf7a2189a56c0dfd10bb37d8316d300dbcd4',
28 gas: '0x15f90',
29 gasPrice: '0x4486199b4',
30 maxFeePerGas: '0x4486199b4',
31 maxPriorityFeePerGas: '0x4486199b4',
32 hash: '0x1c22aee60a6121ce29073a1771155216ccee54962cb235c0ec8d71b6449dd708',
33 input: '0x2d2da806000000000000000000000000accbbf7a2189a56c0dfd10bb37d8316d300dbcd4',
34 nonce: '0x4',
35 to: '0xabea9132b05a70803a4e85094fd0e1800777fbef',
36 transactionIndex: '0xaf',
37 value: '0x38866cac3c00',
38 type: '0x2',
39 accessList: [],
40 chainId: '0x1',
41 v: '0x1',
42 r: '0x7a7a294c5844a2b16f8b2cd5ddc3b748e3ab89215f6974f82910d95d5707b47a',
43 s: '0x79f17cec79d3a66b89780345831408288c9a2c535548c5df35fd9df0692ab5a3'
44 }
45}

Step 6: Filter Mined Transactions

Next, we’ll demonstrate how to filter mined transactions based on addresses. While standard WebSocket subscriptions don’t offer built-in filtering, we can implement filtering logic in our application.

Note: The Alchemy-enhanced alchemy_minedTransactions API provides native filtering by addresses, includeRemoved, and hashesOnly. For standard WebSocket subscriptions, we need to implement filtering manually as shown below.

Add the following code to the main.js file, using your Alchemy API key:

1import { createPublicClient, webSocket } from 'viem'
2import { mainnet } from 'viem/chains'
3
4const client = createPublicClient({
5 chain: mainnet,
6 transport: webSocket('wss://eth-mainnet.g.alchemy.com/v2/<-- ALCHEMY APP API KEY -->')
7})
8
9// Address to filter for
10const targetAddress = "0x473780deaf4a2ac070bbba936b0cdefe7f267dfc"
11
12// Subscribe to new blocks and filter transactions
13const unsubscribe = client.watchBlocks({
14 onBlock: async (block) => {
15 try {
16 const blockWithTxs = await client.getBlock({
17 blockNumber: block.number,
18 includeTransactions: true
19 })
20
21 // Filter transactions by from/to address
22 const filteredTxs = blockWithTxs.transactions.filter(tx =>
23 tx.from?.toLowerCase() === targetAddress.toLowerCase() ||
24 tx.to?.toLowerCase() === targetAddress.toLowerCase()
25 )
26
27 if (filteredTxs.length > 0) {
28 console.log(`Block ${block.number}: Found ${filteredTxs.length} filtered transactions`)
29 filteredTxs.forEach(tx => {
30 console.log('Filtered mined transaction:', {
31 hash: tx.hash,
32 from: tx.from,
33 to: tx.to,
34 value: tx.value?.toString()
35 })
36 })
37 }
38 } catch (error) {
39 console.error('Error processing block:', error)
40 }
41 }
42})
43
44console.log(`Listening for mined transactions involving ${targetAddress}...`)

Conclusion

You now know how to use WebSocket connections with Viem and Ethers.js to subscribe to mined transactions and filter them based on addresses.

For more advanced filtering capabilities, consider using Alchemy’s enhanced alchemy_minedTransactions API which provides native filtering by addresses, includeRemoved, and hashesOnly parameters.

If you enjoyed this tutorial, tweet us at @Alchemy.

If you have any questions or feedback, please contact us at [email protected] or open a ticket in the dashboard.