Fetching Token Holders
Fetching token holders is a vital process that allows you to obtain a list of all wallets addresses that hold a specific token.
What you'll need:
This is useful for several reasons:
- User Base Identification: You can easily identify your user base by fetching token holders.
- Loyalty Rewards: Reward your loyal users by selectively minting new tokens for them.
- Valuable Insights: Analyze user behavior and interactions to gain valuable insights.
- Engage Power Users: Recognize and engage with influential power users who hold a significant amount of tokens.
- Improved User Experience: By retrieving token holder data, you can enhance the overall user experience and make informed, data-driven decisions.
Fetching Token Holders with the Enjin API
To get holders of a specific token, we use the GetToken
query and include the the accounts
in the query response:
Query:
query FetchingTokenHolders{
GetToken(
collectionId: 36105 #Specify the collection ID
tokenId: {integer: 0} #Specify the token ID
){
accounts{
edges{
node{
balance
wallet{
account{
address
}
}
}
}
}
}
}
using System.Text.Json;
using Enjin.Platform.Sdk;
// Setup the query
var getToken = new GetToken()
.SetCollectionId(36105)
.SetTokenId(new EncodableTokenIdInput().SetInteger(0));
// Define and assign the return data fragment to the query
var tokenFragment = new TokenFragment()
.WithAccounts(new ConnectionFragment<TokenAccountFragment>()
.WithEdges(new EdgeFragment<TokenAccountFragment>()
.WithNode(new TokenAccountFragment()
.WithBalance()
.WithWallet(new WalletFragment()
.WithAccount(new AccountFragment()
.WithAddress()
)
)
)
)
);
getToken.Fragment(tokenFragment);
// Create and auth a client to send the request to the platform
var client = PlatformClient.Builder()
.SetBaseAddress("https://platform.canary.enjin.io")
.Build();
client.Auth("Your_Platform_Token_Here");
// Send the request and write the output to the console.
// Only the fields that were requested in the fragment will be filled in,
// other fields which weren't requested in the fragment will be set to null.
var response = await client.SendGetToken(getToken);
Console.WriteLine(JsonSerializer.Serialize(response.Result.Data));
#include "EnjinPlatformSdk/CoreQueries.hpp"
#include <iostream>
using namespace enjin::platform::sdk;
using namespace std;
int main() {
// Setup an Encodable Token ID
EncodableTokenIdInput tokenId = EncodableTokenIdInput()
.SetInteger(make_shared<SerializableString>("0"));
// Set up the query
GetToken getToken = GetToken()
.SetCollectionId(make_shared<SerializableString>("36105"))
.SetTokenId(make_shared<EncodableTokenIdInput>(tokenId));
// Define and assign the return data fragments to the query
AccountFragment accountFragment = AccountFragment()
.WithAddress();
WalletFragment walletFragment = WalletFragment()
.WithAccount(make_shared<AccountFragment>(accountFragment));
TokenAccountFragment tokenAccountFragment = TokenAccountFragment()
.WithBalance()
.WithWallet(make_shared<WalletFragment>(walletFragment));
EdgeFragment<TokenAccountFragment> edgeFragment = EdgeFragment<TokenAccountFragment>()
.WithNode(make_shared<TokenAccountFragment>(tokenAccountFragment));
ConnectionFragment<TokenAccountFragment> connectionFragment = ConnectionFragment<TokenAccountFragment>()
.WithEdges(make_shared<EdgeFragment<TokenAccountFragment>>(edgeFragment));
TokenFragment tokenFragment = TokenFragment()
.WithAccounts(make_shared<ConnectionFragment<TokenAccountFragment>>(connectionFragment));
getToken.SetFragment(make_shared<TokenFragment>(tokenFragment));
// Create and auth a client to send the request to the platform
unique_ptr<PlatformClient> client = PlatformClient::Builder()
.SetBaseAddress("https://platform.canary.enjin.io")
.Build();
client->Auth("Your_Platform_Token_Here");
// Send the request then get the response and write the output to the console.
// Only the fields that were requested in the fragment will be filled in,
// other fields which weren't requested in the fragment will be set to null.
future<PlatformResponsePtr<GraphQlResponse<Token>>> futureResponse = SendGetToken(*client, getToken);
// Get the platform response holding the HTTP data
PlatformResponsePtr<GraphQlResponse<Token>> response = futureResponse.get();
// Get the result, a GraphQL response, holding the GraphQL data
const optional<GraphQlResponse<Token>>& gqlResult = response->GetResult();
// Write the result data to the console
if (gqlResult.has_value() && gqlResult->IsSuccess())
{
const optional<Token>& getTokenResult = gqlResult->GetData()->GetResult();
std::cout << getTokenResult->GetMinimumBalance().value() << std::endl;
}
// Write any error messages to the console
if (gqlResult.has_value() && gqlResult->HasErrors())
{
const optional<vector<GraphQlError>>& errors = gqlResult->GetErrors();
for (const GraphQlError& error : errors.value()) {
std::cout << error.GetMessage().value() << std::endl;
}
}
client.reset();
return 0;
}
fetch('https://platform.canary.enjin.io/graphql', {
method: 'POST',
headers: {'Content-Type': 'application/json','Authorization': 'Your_Platform_Token_Here'},
body: JSON.stringify({
query: `
query FetchingTokenHolders
(
$collection_id: BigInt!
$token_id: BigInt!
) {
GetToken(
collectionId: $collection_id
tokenId: {integer: $token_id}
){
accounts{
edges{
node{
balance
wallet{
account{
address
}
}
}
}
}
}
}
`,
variables: {
collection_id: 36105, //Specify the collection ID
token_id: 0 //Specify the token ID
}
}),
})
.then(response => response.json())
.then(data => console.log(data));
const axios = require('axios');
axios.post('https://platform.canary.enjin.io/graphql', {
query: `
query FetchingTokenHolders
(
$collection_id: BigInt!
$token_id: BigInt!
) {
GetToken(
collectionId: $collection_id
tokenId: {integer: $token_id}
){
accounts{
edges{
node{
balance
wallet{
account{
address
}
}
}
}
}
}
}
`,
variables: {
collection_id: 36105, //Specify the collection ID
token_id: 0 //Specify the token ID
}
}, {
headers: {'Content-Type': 'application/json','Authorization': 'Your_Platform_Token_Here'}
})
.then(response => console.log(response.data))
.catch(error => console.error(error));
import requests
query = '''
query FetchingTokenHolders
(
$collection_id: BigInt!
$token_id: BigInt!
) {
GetToken(
collectionId: $collection_id
tokenId: {integer: $token_id}
){
accounts{
edges{
node{
balance
wallet{
account{
address
}
}
}
}
}
}
}
'''
variables = {
'collection_id': 36105, #Specify the collection ID
'token_id': 0 #Specify the token ID
}
response = requests.post('https://platform.canary.enjin.io/graphql',
json={'query': query, 'variables': variables},
headers={'Content-Type': 'application/json', 'Authorization': 'Your_Platform_Token_Here'}
)
print(response.json())
Response:
{
"data": {
"GetToken": {
"accounts": {
"edges": [
{
"node": {
"balance": "4",
"wallet": {
"account": {
"address": "cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f"
}
}
}
},
{
"node": {
"balance": "2",
"wallet": {
"account": {
"address": "cxJXQKFB4ZWJzutwEtZvTQ9KLucdsaWgzyef5pv9R7x98Dmwp"
}
}
}
}
]
}
}
}
}
Using Pagination
The response may be displayed on several pages. To view all of it, you may need to follow steps for pagination which allows you to flip through the pages.
Fetching Collection Holders with the Enjin API
For an NFT collection, we can use the GetCollection
query and include the the accounts
in the query response to find out how many NFTs from the collection are owned by each address.
Query:
query FetchingCollectionHolders{
GetCollection(collectionId: 36105){ #Specify the collection ID
accounts{
edges{
node{
accountCount
wallet{
account{
address
}
}
}
}
}
}
}
using System.Text.Json;
using Enjin.Platform.Sdk;
// Setup the query
var getCollection = new GetCollection()
.SetCollectionId(36105);
// Define and assign the return data fragment to the query
var collectionFragment = new CollectionFragment()
.WithAccounts(new ConnectionFragment<CollectionAccountFragment>()
.WithEdges(new EdgeFragment<CollectionAccountFragment>()
.WithNode(new CollectionAccountFragment()
.WithAccountCount()
.WithWallet(new WalletFragment()
.WithAccount(new AccountFragment()
.WithAddress()
)
)
)
)
);
getCollection.Fragment(collectionFragment);
// Create and auth a client to send the request to the platform
var client = PlatformClient.Builder()
.SetBaseAddress("https://platform.canary.enjin.io")
.Build();
client.Auth("Your_Platform_Token_Here");
// Send the request and write the output to the console.
// Only the fields that were requested in the fragment will be filled in,
// other fields which weren't requested in the fragment will be set to null.
var response = await client.SendGetCollection(getCollection);
Console.WriteLine(JsonSerializer.Serialize(response.Result.Data)); CC
#include "EnjinPlatformSdk/CoreQueries.hpp"
#include <iostream>
using namespace enjin::platform::sdk;
using namespace std;
int main() {
// Set up the query
GetCollection getCollection = GetCollection()
.SetCollectionId(make_shared<SerializableString>("36105"));
// Define and assign the return data fragments to the query
CollectionAccountFragment collectionAccountFragment = CollectionAccountFragment()
.WithAccountCount()
.WithWallet(make_shared<WalletFragment>(WalletFragment()
.WithAccount(make_shared<AccountFragment>(AccountFragment()
.WithAddress()
)
)
)
);
EdgeFragment<CollectionAccountFragment> edgeFragment = EdgeFragment<CollectionAccountFragment>()
.WithNode(make_shared<CollectionAccountFragment>(collectionAccountFragment));
ConnectionFragment<CollectionAccountFragment> connectionFragment = ConnectionFragment<CollectionAccountFragment>()
.WithEdges(make_shared<EdgeFragment<CollectionAccountFragment>>(edgeFragment));
CollectionFragment collectionFragment = CollectionFragment()
.WithAccounts(make_shared<ConnectionFragment<CollectionAccountFragment>>(connectionFragment));
getCollection.SetFragment(make_shared<CollectionFragment>(collectionFragment));
// Create and auth a client to send the request to the platform
unique_ptr<PlatformClient> client = PlatformClient::Builder()
.SetBaseAddress("https://platform.canary.enjin.io")
.Build();
client->Auth("Your_Platform_Token_Here");
// Send the request then get the response and write the output to the console.
// Only the fields that were requested in the fragment will be filled in,
// other fields which weren't requested in the fragment will be set to null.
future<PlatformResponsePtr<GraphQlResponse<Collection>>> futureResponse = SendGetCollection(*client, getCollection);
// Get the platform response holding the HTTP data
PlatformResponsePtr<GraphQlResponse<Collection>> response = futureResponse.get();
// Get the result, a GraphQL response, holding the GraphQL data
const optional<GraphQlResponse<Collection>>& gqlResult = response->GetResult();
// Write the result data to the console
if (gqlResult.has_value() && gqlResult->IsSuccess())
{
const optional<Collection>& getCollectionResult = gqlResult->GetData()->GetResult();
std::cout << getCollectionResult->GetCollectionId().value() << std::endl;
}
// Write any error messages to the console
if (gqlResult.has_value() && gqlResult->HasErrors())
{
const optional<vector<GraphQlError>>& errors = gqlResult->GetErrors();
for (const GraphQlError& error : errors.value()) {
std::cout << error.GetMessage().value() << std::endl;
}
}
client.reset();
return 0;
}
fetch('https://platform.canary.enjin.io/graphql', {
method: 'POST',
headers: {'Content-Type': 'application/json','Authorization': 'Your_Platform_Token_Here'},
body: JSON.stringify({
query: `
query FetchingCollectionHolders
(
$collection_id: BigInt!
) {
GetCollection(collectionId: $collection_id){
accounts{
edges{
node{
accountCount
wallet{
account{
address
}
}
}
}
}
}
}
`,
variables: {
collection_id: 36105 //Specify the collection ID
}
}),
})
.then(response => response.json())
.then(data => console.log(data));
const axios = require('axios');
axios.post('https://platform.canary.enjin.io/graphql', {
query: `
query FetchingCollectionHolders
(
$collection_id: BigInt!
) {
GetCollection(collectionId: $collection_id){
accounts{
edges{
node{
accountCount
wallet{
account{
address
}
}
}
}
}
}
}
`,
variables: {
collection_id: 36105 //Specify the collection ID
}
}, {
headers: {'Content-Type': 'application/json','Authorization': 'Your_Platform_Token_Here'}
})
.then(response => console.log(response.data))
.catch(error => console.error(error));
import requests
query = '''
query FetchingCollectionHolders
(
$collection_id: BigInt!
) {
GetCollection(collectionId: $collection_id){
accounts{
edges{
node{
accountCount
wallet{
account{
address
}
}
}
}
}
}
}
'''
variables = {
'collection_id': 36105 #Specify the collection ID
}
response = requests.post('https://platform.canary.enjin.io/graphql',
json={'query': query, 'variables': variables},
headers={'Content-Type': 'application/json', 'Authorization': 'Your_Platform_Token_Here'}
)
print(response.json())
Response:
{
"data": {
"GetCollection": {
"accounts": {
"edges": [
{
"node": {
"accountCount": 3,
"wallet": {
"account": {
"address": "cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f"
}
}
}
},
{
"node": {
"accountCount": 2,
"wallet": {
"account": {
"address": "cxJXQKFB4ZWJzutwEtZvTQ9KLucdsaWgzyef5pv9R7x98Dmwp"
}
}
}
}
]
}
}
}
}
Using Pagination
The response may be displayed on several pages. To view all of it, you may need to follow steps for pagination which allows you to flip through the pages.
More Fields and Arguments Available!
The
GetToken
andGetCollection
queries have a range of options beyond the simple examples shown. For full details on these queries, consult the GraphQL Schema on Apollo:
- For
GetToken
query specifics: Apollo GraphQL Schema - GetToken.- For
GetCollection
query specifics: Apollo GraphQL Schema - GetCollection.These links provide the information you need to customize the queries for your needs, including selecting different information about tokens such as attributes and supply details.
Updated about 6 hours ago