Docs

token_activities

NFT activities and ownership queries

Coming soon: Need support for this? Email support@dwellir.com and we will enable it for you.

Token activities tracking provides comprehensive visibility into NFT and token operations on Aptos, including mints, transfers, burns, and marketplace interactions. The GraphQL API enables querying of activity histories, ownership changes, and collection analytics essential for NFT marketplaces, portfolio trackers, and blockchain explorers.

Overview

Every NFT interaction on Aptos generates events that are indexed and made queryable through GraphQL. Token activities encompass all operations affecting digital assets - from initial minting through transfers, sales, and eventual burning. This data enables applications to display transaction histories, track provenance, analyze trading patterns, and provide real-time notifications for NFT-related events.

Core Query Patterns

User Activity History

graphql
query TokenTransfers($owner: String!, $limit: Int!) {
  token_activities_v2(
    where: { owner_address: { _eq: $owner } },
    limit: $limit,
    order_by: { transaction_version: desc }
  ) {
    transaction_version
    event_account_address
    token_standard
    from_address
    to_address
    token_data_id
    amount
    type
    transaction_timestamp
    token_data {
      token_name
      collection_id
      current_collection {
        collection_name
        creator_address
      }
    }
  }
}

Collection Activity Feed

graphql
query CollectionActivities($collection_id: String!, $limit: Int!) {
  token_activities_v2(
    where: {
      token_data: {
        collection_id: { _eq: $collection_id }
      }
    },
    order_by: { transaction_version: desc },
    limit: $limit
  ) {
    type
    from_address
    to_address
    token_data_id
    transaction_timestamp
    transaction_version
  }
}

Recent Mints

graphql
query RecentMints($collection_id: String!) {
  token_activities_v2(
    where: {
      type: { _eq: "0x4::token::MintEvent" },
      token_data: {
        collection_id: { _eq: $collection_id }
      }
    },
    order_by: { transaction_version: desc },
    limit: 50
  ) {
    to_address
    token_data_id
    transaction_timestamp
    transaction_version
  }
}

Sales and Transfers

graphql
query TokenSales($token_data_id: String!) {
  token_activities_v2(
    where: {
      token_data_id: { _eq: $token_data_id },
      type: { _in: ["0x4::token::TransferEvent", "marketplace_sale"] }
    },
    order_by: { transaction_version: desc }
  ) {
    type
    from_address
    to_address
    transaction_version
    transaction_timestamp
    event_account_address
  }
}

Burn Events

graphql
query BurnedTokens($collection_id: String!) {
  token_activities_v2(
    where: {
      type: { _eq: "0x4::token::BurnEvent" },
      token_data: {
        collection_id: { _eq: $collection_id }
      }
    },
    order_by: { transaction_version: desc }
  ) {
    token_data_id
    from_address
    transaction_timestamp
  }
}

Real-World Use Cases

  1. NFT Marketplaces: Display comprehensive activity feeds showing mints, listings, sales, and transfers for collections and individual NFTs with real-time updates.

  2. Portfolio Trackers: Show users their complete NFT transaction history including acquisitions, sales, transfers, and current holdings across all collections.

  3. Collection Analytics: Analyze trading volumes, mint rates, holder behavior, and price trends for NFT collections to provide market intelligence.

  4. Provenance Tracking: Build complete ownership histories showing every transfer from mint to current owner for authenticity verification.

  5. Notification Systems: Alert users instantly when their NFTs are transferred, listed, sold, or when new items mint in collections they follow.

  6. Marketplace Aggregators: Combine activity data from multiple marketplaces to provide comprehensive views of NFT trading across the ecosystem.

Best Practices

Filter by Activity Type: Use the type field to distinguish between mints, transfers, burns, and marketplace events for appropriate handling.

Paginate Results: Implement cursor-based pagination for activity feeds to efficiently handle collections with high volumes of transactions.

Join with Token Data: Always join activities with token_data to fetch metadata (names, images, attributes) for display.

Cache Collection Metadata: Collection-level data changes rarely - cache it aggressively to reduce duplicate queries.

Handle Missing Data: Not all activities have complete metadata - implement fallbacks for missing names, images, or attributes.

Time-Based Filtering: Use transaction_timestamp for date range queries when analyzing historical trends or generating reports.

Aggregate for Statistics: Use aggregate queries to compute volumes, counts, and other metrics rather than client-side processing.

TypeScript Integration

TypeScript
import { ApolloClient, gql } from "@apollo/client";

const client = new ApolloClient({
  uri: "https://api-aptos-mainnet.n.dwellir.com/YOUR_API_KEY/v1/graphql"
});

interface TokenActivity {
  type: string;
  fromAddress: string;
  toAddress: string;
  tokenDataId: string;
  timestamp: string;
  tokenName: string;
  collectionName: string;
}

async function getActivityFeed(address: string, limit: number = 50): Promise<TokenActivity[]> {
  const { data } = await client.query({
    query: gql`
      query ActivityFeed($address: String!, $limit: Int!) {
        token_activities_v2(
          where: {
            _or: [
              { from_address: { _eq: $address } },
              { to_address: { _eq: $address } }
            ]
          },
          order_by: { transaction_version: desc },
          limit: $limit
        ) {
          type
          from_address
          to_address
          token_data_id
          transaction_timestamp
          token_data {
            token_name
            current_collection {
              collection_name
            }
          }
        }
      }
    `,
    variables: { address, limit }
  });

  return data.token_activities_v2.map((activity: any) => ({
    type: activity.type,
    fromAddress: activity.from_address,
    toAddress: activity.to_address,
    tokenDataId: activity.token_data_id,
    timestamp: activity.transaction_timestamp,
    tokenName: activity.token_data?.token_name || "Unknown",
    collectionName: activity.token_data?.current_collection?.collection_name || "Unknown"
  }));
}

// Format activity for display
function formatActivity(activity: TokenActivity): string {
  if (activity.type.includes("Mint")) {
    return `Minted ${activity.tokenName}`;
  } else if (activity.type.includes("Transfer")) {
    return `Transferred ${activity.tokenName} from ${activity.fromAddress.substring(0, 6)}... to ${activity.toAddress.substring(0, 6)}...`;
  } else if (activity.type.includes("Burn")) {
    return `Burned ${activity.tokenName}`;
  }
  return `${activity.type} - ${activity.tokenName}`;
}

Advanced Queries

Collection Trading Volume

graphql
query TradingVolume($collection_id: String!, $since: timestamp!) {
  token_activities_v2_aggregate(
    where: {
      token_data: {
        collection_id: { _eq: $collection_id }
      },
      type: { _in: ["marketplace_sale", "0x4::token::TransferEvent"] },
      transaction_timestamp: { _gte: $since }
    }
  ) {
    aggregate {
      count
    }
  }

  activities: token_activities_v2(
    where: {
      token_data: {
        collection_id: { _eq: $collection_id }
      },
      type: { _in: ["marketplace_sale"] },
      transaction_timestamp: { _gte: $since }
    },
    order_by: { transaction_timestamp: desc }
  ) {
    transaction_timestamp
    from_address
    to_address
    token_data_id
  }
}

Most Active Traders

graphql
query ActiveTraders($collection_id: String!, $days: Int!) {
  token_activities_v2(
    where: {
      token_data: {
        collection_id: { _eq: $collection_id }
      },
      transaction_timestamp: { _gte: "now() - ${days} days" }
    },
    distinct_on: from_address
  ) {
    from_address
  }
}

Token Provenance Chain

graphql
query TokenHistory($token_data_id: String!) {
  token_activities_v2(
    where: { token_data_id: { _eq: $token_data_id } },
    order_by: { transaction_version: asc }
  ) {
    type
    from_address
    to_address
    transaction_version
    transaction_timestamp
    event_account_address
  }
}

Activity Type Classification

Common activity types and their meanings:

  • 0x4::token::MintEvent: NFT was minted
  • 0x4::token::TransferEvent: NFT was transferred
  • 0x4::token::BurnEvent: NFT was burned/destroyed
  • marketplace_listing: NFT was listed for sale
  • marketplace_sale: NFT was sold
  • marketplace_delist: Listing was cancelled

Pagination Pattern

TypeScript
async function getPaginatedActivities(
  address: string,
  limit: number,
  offset: number
): Promise<TokenActivity[]> {
  const { data } = await client.query({
    query: gql`
      query PaginatedActivities($address: String!, $limit: Int!, $offset: Int!) {
        token_activities_v2(
          where: { owner_address: { _eq: $address } },
          order_by: { transaction_version: desc },
          limit: $limit,
          offset: $offset
        ) {
          # fields...
        }
      }
    `,
    variables: { address, limit, offset }
  });

  return data.token_activities_v2;
}