Schema Reference
The GraphQL API provides access to ERC token data through nine tables. This page details the available fields, data types, and relationships. The generated erc schema reference lists every column with its Postgres and GraphQL type.
| Table | Contents |
|---|---|
erc_token | One row per token contract, all standards |
erc_token_account | Balances for ERC-20, ERC-721, ERC-1400, and ERC-3643 |
erc_token_partition_balance | ERC-1400 balances per partition |
erc_multi_token_account | ERC-1155 balances per token type (sub_token_id) |
erc_nft | Individual ERC-721 NFTs |
erc_token_transfer | ERC-20, ERC-1400, and ERC-3643 transfer history |
erc_nft_transfer | ERC-721 transfer history |
erc_multi_token_transfer | ERC-1155 transfer history |
erc_watermark | Indexer progress, for freshness checks |
erc_token
Stores metadata for pure ERC token contracts deployed to Hedera's EVM.
Fields
| Field | Type | Description |
|---|---|---|
token_id | bigint | Hedera entity ID for the contract |
token_evm_address | string | Contract's EVM address (0x format) |
contract_type | string | Token standard; see Contract Types |
name | string | Token name |
symbol | string | Token symbol |
decimals | bigint | Decimal places (fungible standards; NULL for ERC-721) |
total_supply | numeric | Total token supply (handles uint256 values) |
metadata_reliability_score | decimal | Quality score from 0.00 to 1.00 |
created_timestamp | bigint | Contract creation time (nanoseconds since epoch) |
processing_timestamp | bigint | Last processing time (nanoseconds since epoch) |
transfers_indexed_timestamp | bigint | Last indexed transfer timestamp (nanoseconds, NULL if not indexed) |
balance_accrues | boolean | True for interest-bearing tokens whose balances grow without Transfer events |
Token Features
- Primary storage for token contract metadata
- Classifies each contract as ERC-20, ERC-721, ERC-1155, ERC-1400, or ERC-3643
- Includes reliability scoring for metadata quality
balance_accruesmarks Aave-style interest-bearing and debt tokens (detected byscaledTotalSupply()); their balances are refreshed on a timer, so they can trail the chain by up to about 15 minutes
erc_token_account
Tracks ERC-20, ERC-1400, and ERC-3643 balances and ERC-721 ownership counts.
Fields
| Field | Type | Description |
|---|---|---|
account_id | bigint | Holder's Hedera account ID; NULL for a holder with no Hedera account |
holder_evm_address | text | Holder's EVM address, set only when account_id is NULL |
holder_key | text | account_id as text, or holder_evm_address for accountless holders |
token_id | bigint | References erc_token |
token_evm_address | text | Token contract's EVM address |
balance | numeric | Balance in the smallest unit (wei), or NFT count for ERC-721 |
balance_timestamp | bigint | Last balance update (nanoseconds since epoch) |
created_timestamp | bigint | First association time (nanoseconds since epoch) |
associated | boolean | Always true for pure ERC tokens |
Account Features
- Balances come from the contract's own
balanceOf(), not from summing Transfer events - An EVM address that maps to a Hedera account (account-num alias or ECDSA alias) is stored by
account_id; both forms of one account collapse to a single row - A holder with no Hedera account (an ECDSA address that was never activated) is still included:
account_idis NULL andholder_evm_addressidentifies it. Filtering only onaccount_idmisses these holders - For ERC-1400,
balanceis the transferable balance frombalanceOf(); the per-partition split is inerc_token_partition_balance - Primary key: (
token_id,holder_key)
erc_token_partition_balance
ERC-1400 balances per partition, computed from the partition events (IssuedByPartition, TransferByPartition, RedeemedByPartition).
Fields
| Field | Type | Description |
|---|---|---|
token_id | bigint | References the ERC-1400 contract in erc_token |
account_id | bigint | Holder's Hedera account ID; NULL for a holder with no Hedera account |
holder_evm_address | text | Holder's EVM address, set only when account_id is NULL |
holder_key | text | account_id as text, or holder_evm_address |
partition_id | text | Partition identifier, 0x hex with leading zero bytes stripped |
balance | numeric | Balance in the partition |
balance_timestamp | bigint | Consensus time of the last partition event counted |
erc_multi_token_account
ERC-1155 balances: one row per holder per token type.
Fields
| Field | Type | Description |
|---|---|---|
token_id | bigint | References the ERC-1155 contract in erc_token |
sub_token_id | numeric | The ERC-1155 token type ID (full uint256 range) |
account_id | bigint | Holder's Hedera account ID; NULL for a holder with no Hedera account |
holder_evm_address | text | Holder's EVM address, set only when account_id is NULL |
holder_key | text | account_id as text, or holder_evm_address |
balance | numeric | Balance of this token type, from balanceOf(address, id) |
balance_timestamp | bigint | Last balance update (nanoseconds since epoch) |
created_timestamp | bigint | First association time (nanoseconds since epoch) |
token_evm_address | text | Token contract's EVM address |
erc_nft
Tracks individual NFTs within ERC-721 collections.
Fields
| Field | Type | Description |
|---|---|---|
token_id | bigint | References the ERC-721 contract in erc_token |
serial_number | numeric | The individual NFT's tokenId (supports full uint256 range) |
account_id | bigint | Current owner's Hedera account ID (NULL for unresolved addresses) |
deleted | boolean | Burn status (true if NFT was burned) |
metadata | bytea | The tokenURI value (e.g., ipfs://... or https://...) |
created_timestamp | bigint | When NFT was first minted (nanoseconds since epoch) |
processing_timestamp | bigint | When this record was processed (nanoseconds since epoch) |
NFT Features
- Individual NFT ownership tracking by tokenId
tokenURIcaptured for each NFT- Burn status tracking via deleted flag
- Supports full uint256 range for tokenIds
Many NFTs have NULL account_id values. This occurs when the owner is an EVM address with no Hedera account. Ownership counts for those owners still appear in erc_token_account, keyed by holder_evm_address.
erc_token_transfer
Stores transfer history for ERC-20, ERC-1400, and ERC-3643 tokens.
Fields
| Field | Type | Description |
|---|---|---|
token_id | bigint | Hedera contract ID for the token |
consensus_timestamp | bigint | Transfer time (nanoseconds since epoch) |
log_index | integer | Event index within transaction |
token_evm_address | text | EVM address of token contract |
contract_type | varchar | The token's standard: ERC_20, ERC_1400, or ERC_3643 |
transaction_hash | text | Transaction hash |
payer_account_id | bigint | Hedera account ID of transaction payer |
payer_evm_address | text | EVM address of payer |
transfer_type | varchar | See Transfer Types |
sender_account_id | bigint | Sender's Hedera account ID, when the event carried one |
sender_evm_address | text | Sender's EVM address |
receiver_account_id | bigint | Receiver's Hedera account ID, when the event carried one |
receiver_evm_address | text | Receiver's EVM address |
amount | numeric | Transfer amount in smallest unit (wei) |
partition_id | text | ERC-1400 partition identifier (NULL for other standards) |
operator_account_id | bigint | Operator account ID (ERC-1400 partition events only) |
operator_evm_address | text | Operator EVM address (ERC-1400 partition events only) |
Account ID Resolution
In the transfer tables, *_account_id is filled only when the event itself carried a Hedera account number (a long-zero address). Transfers between ECDSA addresses, which are most of them, store only *_evm_address. To find an account's transfers, match on its EVM address as well as its account ID; see Account Transfer History.
Transfer Types
| Type | Standard | Description |
|---|---|---|
transfer | ERC-20, ERC-1400, ERC-3643 | Standard token transfer |
mint | ERC-20, ERC-1400, ERC-3643 | Token creation; sender_account_id is 0 (the zero address) |
burn | ERC-20, ERC-1400, ERC-3643 | Token destruction; receiver_account_id is 0 (the zero address) |
partition_mint | ERC-1400 only | Issuance to a partition (IssuedByPartition); no sender |
partition_transfer | ERC-1400 only | Transfer within a partition (TransferByPartition) |
partition_burn | ERC-1400 only | Redemption from a partition (RedeemedByPartition); no receiver |
An ERC-1400 contract emits both a standard Transfer event and a partition event for the same movement, so its history contains both a mint/transfer/burn row and a partition_* row. To total volume, count one family, not both.
erc_nft_transfer
Stores transfer history for ERC-721 NFTs.
Fields
| Field | Type | Description |
|---|---|---|
token_id | bigint | Hedera contract ID for the NFT collection |
serial_number | numeric | NFT tokenId within the collection |
consensus_timestamp | bigint | Transfer time (nanoseconds since epoch) |
log_index | integer | Event index within transaction |
token_evm_address | text | EVM address of NFT contract |
transaction_hash | text | Transaction hash |
payer_account_id | bigint | Hedera account ID of transaction payer |
payer_evm_address | text | EVM address of payer |
transfer_type | varchar | Type: transfer, mint, burn |
sender_account_id | bigint | Sender's Hedera account ID, when the event carried one |
sender_evm_address | text | Sender's EVM address |
receiver_account_id | bigint | Receiver's Hedera account ID, when the event carried one |
receiver_evm_address | text | Receiver's EVM address |
erc_multi_token_transfer
Stores ERC-1155 transfer history from TransferSingle and TransferBatch events. A batch event produces one row per token type it moves.
Fields
| Field | Type | Description |
|---|---|---|
token_id | bigint | Hedera contract ID for the ERC-1155 contract |
sub_token_id | numeric | The ERC-1155 token type ID |
consensus_timestamp | bigint | Transfer time (nanoseconds since epoch) |
log_index | integer | Event index within transaction |
token_evm_address | text | EVM address of the contract |
transaction_hash | text | Transaction hash |
payer_account_id | bigint | Hedera account ID of transaction payer |
payer_evm_address | text | EVM address of payer |
transfer_type | varchar | Type: transfer, mint, burn |
sender_account_id | bigint | Sender's Hedera account ID, when the event carried one |
sender_evm_address | text | Sender's EVM address |
receiver_account_id | bigint | Receiver's Hedera account ID, when the event carried one |
receiver_evm_address | text | Receiver's EVM address |
operator_account_id | bigint | Operator's Hedera account ID, when the event carried one |
operator_evm_address | text | Operator's EVM address |
amount | numeric | Amount of this token type moved |
erc_watermark
Indexer progress. Every transfer event at or before last_processed_ns for the transfer_indexing job is present in the transfer tables.
| Field | Type | Description |
|---|---|---|
job_name | text | transfer_indexing for the live indexer |
last_processed_ns | bigint | Consensus time indexed up to (nanoseconds) |
last_processed_ns_iso8601 | text | The same time as an ISO 8601 string |
updated_at | timestamptz | When the watermark last moved |
Data Types and Constraints
Numeric Types
- BIGINT: Used for Hedera IDs, timestamps, and counts
- NUMERIC: Used for balances, supplies, and ERC-1155 token type IDs (handles uint256 values up to 2^256-1)
- DECIMAL(3,2): Used for reliability scores (0.00 to 1.00)
Timestamp Formats
All timestamps use nanoseconds since epoch (Hedera format):
- created_timestamp: Contract/entity creation time
- balance_timestamp: Last balance update time
- processing_timestamp: When the record was processed/synced
- transfers_indexed_timestamp: Last indexed transfer time
- consensus_timestamp: Transaction consensus time (transfer tables)
Contract Types
Values of the contract_type field:
ERC_20: ERC-20 fungible tokenERC_721: ERC-721 NFT collectionERC_1155: ERC-1155 multi-token contractERC_1400: ERC-1400 security tokenERC_3643: ERC-3643 (T-REX) permissioned token
Relationships
These GraphQL relationships can be nested in a query:
| From | Field | To |
|---|---|---|
erc_token | nft | erc_nft (many) |
erc_token | token_partition_balance | erc_token_partition_balance (many) |
erc_token | multi_token_account | erc_multi_token_account (many) |
erc_token_account | token | erc_token (one) |
erc_token_account | nft | that holder's erc_nft rows (many) |
erc_token_partition_balance | token | erc_token (one) |
erc_multi_token_account | token | erc_token (one) |
erc_multi_token_transfer | token | erc_token (one) |
The fungible and NFT transfer tables have no relationships; join them to erc_token by token_id in a separate query.
Query Examples
Get a token's holders with token metadata
query GetTokenHolders($tokenId: bigint!) {
erc_token_account(
where: { token_id: { _eq: $tokenId }, balance: { _gt: "0" } }
order_by: { balance: desc }
limit: 100
) {
account_id
holder_evm_address
balance
balance_timestamp
token {
name
symbol
decimals
}
}
}
Get NFT collection with individual NFTs
query GetNFTCollection($tokenId: bigint!) {
erc_token_by_pk(token_id: $tokenId) {
token_id
name
symbol
total_supply
nft(where: { deleted: { _eq: false } }, order_by: { serial_number: asc }, limit: 100) {
serial_number
account_id
metadata
created_timestamp
}
}
}
Get an ERC-1155 contract's holders by token type
query GetMultiTokenHolders($tokenId: bigint!) {
erc_multi_token_account(
where: { token_id: { _eq: $tokenId }, balance: { _gt: "0" } }
order_by: [{ sub_token_id: asc }, { balance: desc }]
) {
sub_token_id
account_id
holder_evm_address
balance
}
}
For more comprehensive query examples, see the Query Examples page.