Web3.js: How to Track NFT (ERC-721/1155) Transfers and Mints (+ Specific Address/NFT)
This tutorial makes use of Web3.js v1.x.x. Not all functionality might work with Web3.js v4.
Events are essential to the Ethereum blockchain; they allow us to create interfaces that update dynamically as contracts complete executions. By watching the events in a block, we can track both NFTs transfers and mints in real-time.
Additionally, we can choose only to track specific NFT transactions or NFT transfers from/to a particular Ethereum address. Let’s learn how!
New ERC-712 transaction found in block 15089164 with hash 0xfe645cb621d0fd11ce7f88c6211525339a2c7d48c2f5b3572fcb6caaaf8d6828
From: 0x2A4b4eC07e380398700E47733e42DB8217f480bd
To: 0xD2e48bA114527126eF20a5b21282ed3AeD7c220a
Token contract: 0xdebb2D5f818B53e0732444b31d4EFe4AF887026A
Token ID: 2834
New ERC-1155 transaction found in block 15089239 with hash 0x43b63c7f0eb9df5a279f69338cc3bc0f935a039a821183a2fdd9cc5d736dfc5f
Operator: 0x1E0049783F008A0085193E00003D00cd54003c71
From: 0x5E5BA665bfaacc1E0eEaD7057CE8251298a60439
To: 0x57E283b1BfFf55471B6c78203a08AcC761DC6Ed4
id: 3
value: 1
Setting Up Our Project
Please create a new folder in which we can work on our project, then install web3js using npm.
npm install web3
Ensure you have your Infura account set up and have access to your endpoint URL. Feel free to read more about getting started with Infura.
At the top of our new Javascript file, we can add the following to import the web3js library that we just installed, and connect to the Infura websockets endpoint:
const Web3 = require("web3");
const web3 = new Web3("wss://mainnet.infura.io/ws/v3/<API_KEY>");
Make sure to replace API_KEY with your actual Infura API KEY.
Reading ERC-721 and ERC-1155 Events
NFTs on the Ethereum blockchain typically use ERC-721 or ERC-1155, both of which are standards for deploying Non-Fungible Tokens to the network. Just like ERC-20 is used for fungible tokens, it allows developers to create a standardized smart contract with which other interfaces can easily interact.
ERC-721 is the most used standard to deploy NFTs on the Ethereum chain, with CryptoKitties kicking off its popularity. These days, while most NFTs get deployed with the ERC-721 spec, ERC-1155 is seeing booming usage, especially for game-related Dapps.
While ERC-721 only allows you to create non-fungible tokens, ERC-1155 supports both fungible- and non-fungible tokens. This ability to support both types of tokens would especially be helpful in games, as a currency could be fungible (like silver or gold), and rare items (like armor or accessories) could be collectibles and thus non-fungible.
Subscribing to Contract Events
The web3.eth.subscribe
function in web3.js allows us to subscribe to events happening on the blockchain. Smart contracts can emit events during execution and are usually used to ‘announce’ that a contract executed a significant action. In our case, it would be the transfer of an NFT, but other examples of events could also include ERC-20 transfers or a swap happening on a decentralized exchange.
There’s a slight difference in the events that these standards emit. ERC-721 transactions emit the following event:
Transfer (address from, address to, uint256 tokenId)
ERC-1155 transactions emit the following event:
TransferSingle (address operator, address from, address to, uint256 id, uint256 value)
ERC-1155 smart contracts can also emit a TransferBatch event for batch transfers, but we won’t track this event in this tutorial.
In order to tell web3.eth.subscribe
which events we should track, we can add the following filters:
let options721 = {
topics: [web3.utils.sha3("Transfer(address,address,uint256)")],
};
let options1155 = {
topics: [
web3.utils.sha3("TransferSingle(address,address,address,uint256,uint256)"),
],
};
Then, initiate the subscriptions using web3.eth.subscribe
with the filters we just set:
let subscription721 = web3.eth.subscribe("logs", options721);
let subscription1155 = web3.eth.subscribe("logs", options1155);
Additionally, we can add the following lines to see whether the subscription started successfully or if any errors occurred:
subscription721.on("error", (err) => {
throw err;
});
subscription1155.on("error", (err) => {
throw err;
});
subscription721.on("connected", (nr) =>
console.log("Subscription on ERC-721 started with ID %s", nr),
);
subscription1155.on("connected", (nr) =>
console.log("Subscription on ERC-1155 started with ID %s", nr),
);