Coming soon: Need support for this? Email support@dwellir.com and we will enable it for you.
GraphQL Aggregations
GraphQL aggregations enable powerful analytical queries on Aptos blockchain data, allowing you to compute statistics, counts, sums, and other aggregate functions across large datasets. These queries are essential for building analytics dashboards, generating reports, and understanding on-chain activity patterns without processing individual records.
Overview#
The Aptos GraphQL indexer provides aggregate functions that operate on filtered datasets, enabling you to answer questions like "How many transactions occurred today?", "What's the total trading volume?", or "Who are the top gas consumers?" These aggregations run efficiently on indexed data, providing fast results even for complex queries spanning millions of records.
Common Aggregate Functions#
The GraphQL API supports standard aggregate operations:
count: Total number of records matching criteria sum: Sum of numeric field values avg: Average of numeric values max: Maximum value in dataset min: Minimum value in dataset stddev: Standard deviation of values variance: Variance of values
Example Queries#
Transaction Volume Analysis#
query TransactionMetrics($startTime: timestamp!, $endTime: timestamp!) {
user_transactions_aggregate(
where: {
timestamp: { _gte: $startTime, _lte: $endTime }
}
) {
aggregate {
count
sum { gas_used }
avg { gas_used }
max { gas_used }
min { gas_used }
}
}
}
Top Gas Consumers#
query TopGasUsers($limit: Int!) {
user_transactions_aggregate {
aggregate { count }
}
user_transactions(
order_by: { gas_used: desc },
limit: $limit
) {
sender
gas_used
version
timestamp
}
}
Daily Active Users#
query DailyActiveUsers($date: date!) {
user_transactions_aggregate(
distinct_on: sender,
where: {
timestamp: {
_gte: $date,
_lt: "${date + 1 day}"
}
}
) {
aggregate {
count(distinct: true, columns: sender)
}
}
}
Token Transfer Statistics#
query TokenTransferStats($token_type: String!) {
coin_activities_aggregate(
where: {
coin_type: { _eq: $token_type },
activity_type: { _eq: "0x1::coin::WithdrawEvent" }
}
) {
aggregate {
count
sum { amount }
avg { amount }
}
}
}
NFT Collection Analytics#
query CollectionMetrics($collection_id: String!) {
current_token_ownerships_v2_aggregate(
where: {
current_token_data: {
collection_id: { _eq: $collection_id }
}
}
) {
aggregate {
count
}
}
token_activities_v2_aggregate(
where: {
token_data_id: { _like: "${collection_id}%" },
type: { _eq: "0x3::token::MintTokenEvent" }
}
) {
aggregate {
count
}
}
}
Real-World Use Cases#
-
Protocol Analytics: Track total value locked, transaction volumes, user growth, and other key metrics for DeFi protocols and dApps.
-
User Behavior Analysis: Understand user engagement patterns, identify power users, and analyze transaction frequency distributions.
-
Gas Optimization Research: Analyze gas consumption patterns to identify optimization opportunities and compare efficiency across different contract designs.
-
Market Intelligence: Aggregate trading volumes, price movements, and liquidity metrics for tokens and NFT collections.
-
Network Health Monitoring: Track transaction success rates, average confirmation times, and network utilization over time.
-
Revenue Reporting: Calculate total fees collected, transaction counts by type, and other financial metrics for business reporting.
Best Practices#
Use Appropriate Filters: Apply WHERE clauses to reduce dataset size before aggregation for better performance.
Leverage Indexed Fields: Aggregations on indexed fields (addresses, timestamps, types) perform significantly faster.
Batch Time-Series Queries: For dashboards displaying multiple time periods, batch queries together to reduce API calls.
Cache Results: Aggregate statistics change slowly - implement appropriate caching strategies to reduce load.
Pagination for Details: When showing aggregate summaries plus details, paginate the detail results appropriately.
Use Variables: Parameterize queries with GraphQL variables for reusable, type-safe queries.
Performance Considerations#
- Aggregations on large unfiltered tables can be slow - always use WHERE clauses
- Distinct counts are more expensive than simple counts
- Complex nested aggregations should be avoided or split into multiple queries
- Consider using materialized views for frequently accessed aggregations
- Time-range queries on timestamp fields are well-optimized
Combining Aggregates with Details#
query DashboardMetrics($limit: Int!) {
# Overall statistics
metrics: user_transactions_aggregate {
aggregate {
count
avg { gas_used }
sum { gas_used }
}
}
# Top performers
top_users: user_transactions(
order_by: { gas_used: desc },
limit: $limit,
distinct_on: sender
) {
sender
gas_used
}
# Recent activity
recent: user_transactions(
order_by: { timestamp: desc },
limit: $limit
) {
hash
sender
timestamp
success
}
}
TypeScript Integration#
import { ApolloClient, gql } from "@apollo/client";
const client = new ApolloClient({
uri: "https://api-aptos-mainnet.n.dwellir.com/YOUR_API_KEY/v1/graphql"
});
const TRANSACTION_STATS = gql`
query TransactionStats {
user_transactions_aggregate {
aggregate {
count
avg { gas_used }
}
}
}
`;
const { data } = await client.query({ query: TRANSACTION_STATS });
console.log(`Total transactions: ${data.user_transactions_aggregate.aggregate.count}`);
console.log(`Average gas: ${data.user_transactions_aggregate.aggregate.avg.gas_used}`);
Related Concepts#
- GraphQL Overview - Introduction to GraphQL indexer
- User Transactions - Query transaction data
- Token Activities - Aggregate token transfers
- ANS Queries - Query naming service data