Indexer & GraphQL API
Overview
A custom indexer is available for integration, providing GraphQL access to indexed on-chain data from Solana RWA programs. The indexer continuously monitors and indexes transactions from all Solana RWA programs, making historical and real-time data easily accessible through a unified GraphQL API.
Key Features
- Multi-Program Indexing: Indexes all Solana RWA programs
- Token-2022 Activity: Indexes Token-2022 mint and burn instructions for registered tokens
- Wallet Roles: Current role mask of each wallet per mint, from the on-chain
WalletRoleaccounts - GraphQL API: Unified GraphQL endpoint with interactive GraphiQL IDE
- Chronological Ordering: All queries return data in chronological order optimized for cap table building
Authentication
The GraphQL endpoint uses API key authentication via the X-API-Key header. The key is available upon request.
Using the API Key
Include the API key in all GraphQL requests using the X-API-Key header:
curl -H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "{ __typename }"}' \
https://solana-rwa-indexer.upside.gg/graphql
Endpoints
Production
- GraphQL Endpoint:
https://solana-rwa-indexer.upside.gg/graphql - GraphiQL IDE:
https://solana-rwa-indexer.upside.gg/graphiql - Health Check:
https://solana-rwa-indexer.upside.gg/health(no authentication required)
Staging
- GraphQL Endpoint:
https://solana-rwa-indexer-staging.upside.gg/graphql - GraphiQL IDE:
https://solana-rwa-indexer-staging.upside.gg/graphiql - Health Check:
https://solana-rwa-indexer-staging.upside.gg/health(no authentication required)
Example Request
# Production
curl -H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "{ __typename }"}' \
https://solana-rwa-indexer.upside.gg/graphql
# Staging
curl -H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "{ __typename }"}' \
https://solana-rwa-indexer-staging.upside.gg/graphql
GraphQL Schema for Cap Table Activity
The indexer provides a unified tokenActivity query that combines all token movements (mints, burns, force transfers, and transfers) in a single sorted list, designed for cap table building.
TokenActivity Query
query TokenActivity($mint: String!, $limit: Int!, $offset: Int!, $order: SortOrder) {
tokenActivity(mint: $mint, limit: $limit, offset: $offset, order: $order) {
activityType # "mint", "burn", "force_transfer", or "transfer"
signature
instructionIndex
innerIndex # Only for transfers (null for other types)
slot
slotTimestamp
stackHeight
amount
mint
createdAt
decimals # Token decimals from mint metadata (null if unknown)
# Authority fields (check activityType to know which are populated)
destinationAuthority # For mints, force_transfers, and transfers
targetAuthority # For burns
sourceAuthority # For force_transfers and transfers
# Enriched metadata (null when no metadata applies)
meta {
eventType
admin
fromAuthority
toAuthority
amount
scheduleId
commencementTimestamp
cancelableBy
scheduleReleaseCount
scheduleDelayUntilFirstReleaseInSeconds
scheduleInitialReleasePortionInBips
schedulePeriodBetweenReleasesInSeconds
timelockId
canceledBy
canceledAmount
paidAmount
target
reclaimer
}
}
}
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
mint | String! | Yes | Token mint address to query |
limit | Int | No | Maximum number of results (default: 100) |
offset | Int | No | Number of results to skip (default: 0) |
order | SortOrder | No | Sort order: ASC (oldest first, default) or DESC (newest first) |
TokenActivity Response Fields
| Field | Type | Description |
|---|---|---|
activityType | String | Type of activity: "mint", "burn", "force_transfer", or "transfer" |
signature | String | Transaction signature (part of unique event ID) |
instructionIndex | Int | Index of instruction within transaction (part of unique event ID) |
innerIndex | Int? | Ordinal within the same outer instruction; only populated for transfer activity type (null for others). Part of the unique event ID for transfers. |
slot | String | Solana slot number |
slotTimestamp | String? | Unix timestamp of the slot |
stackHeight | Int? | Call stack height (1 = outer, >=2 = inner/CPI) |
amount | String | Token amount (as decimal string) |
mint | String | Token mint address |
createdAt | String? | Timestamp when record was indexed |
decimals | Int? | Token decimals from mint metadata. Null if the mint was not initialized through AccessControl. |
destinationAuthority | String? | Destination authority (populated for mints, force_transfers, and transfers) |
targetAuthority | String? | Target authority (populated for burns) |
sourceAuthority | String? | Source authority (populated for force_transfers and transfers) |
meta | TokenActivityMeta? | Enriched metadata for specific event types (see below) |
The unique identifier for each event is a composite key of signature + instructionIndex + innerIndex. For non-transfer activity types, the GraphQL API returns innerIndex as null; when constructing composite keys, clients should treat null as 0 to maintain a consistent identifier format.