• Pricing
  • Enterprise
  • Customers
  • Blog

How to track swaps on Uniswap with web3.js?

In just 5 minutes you will learn how to leverage web3.js and WebSocket endpoints to monitor swaps on Uniswap.

The idea for this tutorial came from one of our Discord members who had a very specific data task on Ethereum. This user wanted to monitor the Uniswap router contract to know whenever an ETH to token swap happens. For example, if someone is swapping 1 ETH to USDC, he wants to extract the transaction ID, the address, and so on, to be displayed in real-time as it gets confirmed.

At first, it seems like an easy task, but if you dive a little bit deeper, you will realize that it’s more complex.

In case you don’t know, the Uniswap router contract does not emit swap events. Swap events are only emitted on the pair itself, not on the router contract.

We’ll be utilizing WebSocket subscriptions to look through every new block that’s added to the Ethereum blockchain, and then within that block, look through each transaction, see if it’s a swap on Uniswap, and then display that information.

While it may sound a little bit complicated, it’s really simple in implementation.

Let’s utilize web3.js and WebSocket endpoints to track swaps on Uniswap.

Import the base libraries

Before we start we need one major base library, and that is web3.js. This will be the only library that we’ll be using, and it will act as our foundational layer of connectivity with the blockchain.

const { Web3 } = require('web3');

Define the RPC node

Now that we have Web3 imported, we need to define an RPC node. We can define this in a variable called NODE_URL.

const NODE_URL =  "input your WSS endpoint here"; //your Chainstack WebSocket endpoint

Deploy your node and get your WebSocket endpoint

If you do not have a Chainstack account yet, you can sign up for free in order to follow along with this tutorial.

After you have your account, you can go ahead and deploy an Ethereum node by following the steps in the video below.

Once your node is running, you can click on it to see its details.

Scroll to the bottom of the page and grab the WSS execution endpoint.

Define the Web3 object with RPC as a constructor

const web3 = new Web3(NODE_URL);

Define three key variables

We only need to find two types of swaps. Either swapExactETHForTokens or a separate method called swapExactETHForTokensSupportingFeeOnTransferTokens, which achieves essentially the same goal, but it’s for a different type of token. This means that we’ll need to define three key variables.

  1. Uniswap router address. We will use the V2 router because it’s easier to show in this example.
  2. The ID of the swapExactETHForTokens method.
  3. The ID of the swapExactETHForTokensSupportingFeeOnTransferTokens method.
const UNISWAP_ROUTER_ADDRESS = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D";
const SWAP_EXACT_ETH_FOR_TOKENS_SIGNATURE = "0x7ff36ab5";
const SWAP_EXACT_ETH_OR_TOKENS_SUPPORTING_FEE_ON_TRANSFER_TOKENS_SIGNATURE = "0xb6f9de95";

Create function subscribeToNewBlocks

Now that we have our variables defined, we can go ahead and create a new function called subscribeToNewBlocks.

async function subscribeToNewBlocks() {
    const subscription = await web3.eth.subscribe('newBlockHeaders');
    subscription.on('data', handleNewBlock);
}
async function handleNewBlock(blockHeader) {
    console.log(`Got new block: ${blockHeader.number}`);
    const block = await web3.eth.getBlock(blockHeader.number, true);
    block.transactions.forEach((tx) => {
      if(tx.to && tx.to.toLowerCase() === UNISWAP_ROUTER_ADDRESS.toLowerCase() && (tx.input.startsWith(SWAP_EXACT_ETH_FOR_TOKENS_SIGNATURE) || (tx.input.startsWith(SWAP_EXACT_ETH_OR_TOKENS_SUPPORTING_FEE_ON_TRANSFER_TOKENS_SIGNATURE))) {
  console.log("-----------------------------------------------------")
  console.log(`Incoming swap transaction: ${tx.hash}`);
  console.log(`From: ${tx.from}`);
  console.log(`Value: ${web3.utils.fromWei(tx.value, "ether")} ETH`);
  console.log("-----------------------------------------------------")
    }
  })
}
subscribeToNewBlocks();

The subscribeToNewBlock function will monitor the Ethereum blockchain, and whenever a new block is created, it will return it so that we can get close to real-time data.

The handleNewBlock function will log every time it finds a new block. Then, it will fetch that block, and loop through the transactions that were included in that block.

If it finds transactions where the to address a.k.a. receiver is THE UNISWAP_ROUTER_ADDRESS, and the method ID matches the method ID of either SWAP_EXACT_ETH_FOR_TOKENS_SIGNATURE or SWAP_EXACT_ETH_OR_TOKENS_SUPPORTING_FEE_ON_TRANSFER_TOKENS_SIGNATURE, it will return that transaction’s hash, the sender, and the amount of ETH that was swapped for a particular token.

Let’s recap what you did

  1. You’ve imported Web3.
  2. Created a Chainstack WebSocket endpoint, and used it in the definition of our Web3 object.
  3. Defined 3 key base variables including the Uniswap V2 router address, and the two method IDs.
  4. Defined the subscribeToNewBlocks function.
  5. Created the function that handles the data when it gets it, which is the handleNewBlock function.

Now, if you run the code it should return the latest block that got confirmed, along with the swap transactions within it.

Congratulations if you got to the end of this tutorial, now you know how to track swaps on Uniswap in real-time on the Ethereum blockchain.

Power-boost your project with Chainstack

Have you already explored what you can achieve with Chainstack? Get started for free today.

SHARE THIS ARTICLE

ERC4626: A new standard for tokenized vaults

Standards like ERC20 and ERC721 are the building blocks that allowed hundreds of apps to appear in recent years. ERC4626 is the latest one for creating tokenized vaults.

Antonio Ufano
May 27