Introduction
Snapshots of NFT holders are an extremely useful tool in the world of web3. With Helius, the process of taking these snapshots is made easy through simple API calls.
To follow along with this tutorial, you'll need a Helius account and API key which you can obtain for free by signing up here. If you have any questions you can refer to the related documentation at the end of the post. Additionally, don't hesitate to join the Helius Discord community or tag Helius on Twitter to ask for further assistance.
What is an NFT snapshot?
An NFT snapshot uses an NFTs mint address to record ownership of a token and can be done for collections to see all the holders of the NFTs. An NFTs mint address is a unique address that identifies an NFT and shows its on chain location. NFT snapshots can be useful to create historical records, reward users, and analyze ownership data.
Steps to take a holder snapshot:
- Get a list of NFT mint addresses that belong to a collection.
- Get the holders of each of those NFTs.
Let's begin by creating a JavaScript file named "holderSnapshot.js". We will be using axios to send HTTP POST requests to the Helius API endpoint, we'll need to install it by running npm install axios in our terminal.
You can now open up the file and start off our code with the required imports.
First, we want to search for NFTs that share the same verified creator address or collection ID. This process is made easy by the API's functionality. The NFT Collection Mintlist API provided by Helius enables the retrieval of mint addresses related to a particular collection through a fetch request sent to the Helius servers hosting the API.
Below is the code for getting all the NFTs that share the same first verified creator address. You can find more information about this here. In this example I will be using the Solana Monkey Business collection.
const mintListURL = `https://api.helius.xyz/v1/mintlist?api-key=`;
const getMintlist = async () => {
const { data } = await axios.post(mintListURL, {
query: {
// SMB
firstVerifiedCreators: ["mdaoxg4DVGptU4WSpzGyVpK3zqsgn7Qzx5XNgWTcEA2"],
},
options: {
limit: 5000,
},
});
console.log(data.result)
// return data.result;
};
getMintlist();
You can also use verifiedCollectionAddresses instead of firstVerifiedCreator if you know the collection address. You can find both the first verified creator and the collection address on a block explorer like Solscan. On Solscan under the creators tab you can view who the first verified creator is:
You can find the collection address under the metadata section on the same page:
The value of the limit option should be a number between 1 and 10 000, the default is 1000. I chose 5000 as the Solana Monkey Business collection has 5000 NFTs.
The output would look similar to this:
{
mint: '5y2TFKg8RDd7C89mC5vMbe765Xq6UGGbc9CjeMPKZeEZ',
name: 'SMB #2891'
},
...
{
mint: '4r3hW92NgmmVsmc7RLKNpud18ftozkU6aAwvUeP7hPzL',
name: 'SMB #348'
},
Next you can replace the getMintlist() function call from the code above and replace it with the following:
const createHolderList = async () => {
const tempArray = [];
const mintArray = await getMintlist();
const mintArrayMapped = mintArray.map((item) => item.mint);
};
createHolderList();
You will also need to uncomment // return data.result in the getMintlist() function.
This will retrieve each mint address and create an array of addresses that we can then use. It will look something like this:
[
'6SBGoegWaq8uF8MuT7cbSPAf6cYJ2JnG5X7U34LCKgvv',
'9hGyf1uSWpba5WNZZt48i6jU5dXvmrfSd7Y9bexqR6sx',
'Axn4kfBLXiRR3LGdXQ5ErbfoM8N8SwCQ7DF6Cy254qTG',
...
]
To figure out the wallet that holds each NFT, we will utilize the getAsset call from Helius’s Digital Asset Standard API. This call will retrieve all the information associated with each token’s mint address. Once we have all the information on a token we can extract the owner from the data.
To make use of the DAS API we will first need to add add our Helius RPC URL to the top of the file under the mintListURL:
const rpcURL = `https://rpc.helius.xyz/?api-key=`;
We will now create a new function called getHolder and add the following code:
const getHolder = async (address) => {
const assetID = address;
const { data } = await axios.post(rpcURL, {
jsonrpc: "2.0",
id: "my-id",
method: "getAsset",
params: [assetID],
});
const owner=data.result.ownership.owner
return owner;
};
Calling this function for each mint address can take a while so to save time we are going to batch addresses together to check them as a group.
The first step to breaking up the data is creating a helper method to split up the mint addresses. We can create a function called chunk :
const chunk = (array, size) => {
const chunked = [];
let index = 0;
while (index < array.length) {
chunked.push(array.slice(index, size + index));
index += size;
}
return chunked;
};
Next we will update the createHoldersList function to create an array containing all the holder addresses. We will add the following code:
// break the array into chunks of 200
const chunks = chunk(mintArrayMapped, 200);
// loop through the chunks and get the owner of each mint
for (const chunk of chunks) {
await Promise.all(
chunk.map(async (mint) => {
const owner = await getHolder(mint);
tempArray.push(owner);
return owner;
})
);
}
console.log(tempArray);
return tempArray;
Now in the createHoldersList function we get the list of NFTs in a collection and extract the mint addresses which we split into chunks. Following this we loop through and use the getHolder() function to get and save the holder of each NFT.
Next we create a function to save the holder addresses to a file on our local machine. We do this in a function called saveHolders in which we call the createHoldersList() function. You can replace the previous createHoldersList() function call with the following code:
const saveHolders = async () => {
const holderArray = await createHoldersList();
console.log(holderArray);
const data = JSON.stringify(holderArray);
fs.writeFile("holders.json", data, (err) => {
if (err) throw err;
console.log("Data saved to file");
});
};
saveHolders();
This code will output the list of holders in a JSON file.
This is a simple and effective way to get a list of all the holders of NFTs in a collection.
The complete code along with output examples can be found here: https://github.com/owenventer/NFT-Holder-Snapshot/blob/main/holderSnapshot.js
Conclusion
So now we've covered the basics of taking NFT holder snapshots using Helius APIs. With this information, we can easily create historical records of ownership, verify the authenticity of an NFT, distribute rewards to users and analyze data on NFT ownership.
References
NFT Collection Mintlists (Helius): https://docs.helius.xyz/solana-apis/nft-api/nft-collection-mintlists
getTokenLargestAccounts (Solana docs): https://docs.solana.com/api/http#gettokenlargestaccounts