Files
explorer-monorepo/docs/specs/api/graphql-api.md

5.4 KiB

GraphQL API Specification

Overview

This document specifies the GraphQL API for the explorer platform, providing flexible queries, mutations for user data, and subscriptions for real-time updates.

Endpoint: https://api.explorer.d-bis.org/graphql

Schema Overview

Core Types

Block

type Block {
  chainId: Int!
  number: BigInt!
  hash: String!
  parentHash: String!
  timestamp: DateTime!
  miner: Address
  transactionCount: Int!
  gasUsed: BigInt!
  gasLimit: BigInt!
  transactions: [Transaction!]!
}

Transaction

type Transaction {
  chainId: Int!
  hash: String!
  block: Block
  blockNumber: BigInt
  from: Address!
  to: Address
  value: BigInt!
  gasPrice: BigInt
  gasUsed: BigInt
  status: TransactionStatus!
  logs: [Log!]!
  traces: [Trace!]!
}

Address

type Address {
  address: String!
  chainId: Int!
  balance: BigInt!
  balanceUSD: Float
  transactionCount: Int!
  transactions: TransactionConnection!
  tokens: [TokenBalance!]!
  nfts: [NFT!]!
  label: String
  tags: [String!]!
  isContract: Boolean!
  contract: Contract
}

Token

type Token {
  address: String!
  chainId: Int!
  name: String
  symbol: String
  type: TokenType!
  decimals: Int
  totalSupply: BigInt
  holderCount: Int!
  transfers: TokenTransferConnection!
  holders: HolderConnection!
}

Contract

type Contract {
  address: String!
  chainId: Int!
  name: String
  verificationStatus: VerificationStatus!
  sourceCode: String
  abi: JSON
  compilerVersion: String
  createdAt: DateTime
}

Queries

Block Queries

query GetBlock($chainId: Int!, $number: BigInt!) {
  block(chainId: $chainId, number: $number) {
    number
    hash
    timestamp
    transactionCount
    transactions {
      hash
      from
      to
      value
    }
  }
}

Transaction Queries

query GetTransaction($chainId: Int!, $hash: String!) {
  transaction(chainId: $chainId, hash: $hash) {
    hash
    from
    to
    value
    status
    logs {
      address
      topics
      data
    }
    traces {
      type
      from
      to
      value
    }
  }
}

Address Queries

query GetAddress($chainId: Int!, $address: String!) {
  address(chainId: $chainId, address: $address) {
    address
    balance
    balanceUSD
    transactionCount
    transactions(first: 10) {
      edges {
        node {
          hash
          blockNumber
          value
        }
      }
    }
    tokens {
      token {
        symbol
        name
      }
      balance
    }
  }
}

Search Query

query Search($query: String!, $chainId: Int) {
  search(query: $query, chainId: $chainId) {
    ... on Block {
      number
      hash
    }
    ... on Transaction {
      hash
      from
      to
    }
    ... on Address {
      address
      label
    }
    ... on Token {
      address
      symbol
      name
    }
  }
}

Mutations

User Preferences

mutation UpdateWatchlist($chainId: Int!, $address: String!, $label: String) {
  addToWatchlist(chainId: $chainId, address: $address, label: $label) {
    success
    watchlistItem {
      address
      label
    }
  }
}

mutation RemoveFromWatchlist($chainId: Int!, $address: String!) {
  removeFromWatchlist(chainId: $chainId, address: $address) {
    success
  }
}

Address Labels

mutation AddAddressLabel($chainId: Int!, $address: String!, $label: String!) {
  addAddressLabel(chainId: $chainId, address: $address, label: $label) {
    success
    label {
      address
      label
    }
  }
}

Subscriptions

New Blocks

subscription NewBlocks($chainId: Int!) {
  newBlock(chainId: $chainId) {
    number
    hash
    timestamp
    transactionCount
  }
}

Address Transactions

subscription AddressTransactions($chainId: Int!, $address: String!) {
  addressTransaction(chainId: $chainId, address: $address) {
    hash
    from
    to
    value
    status
  }
}

Pending Transactions

subscription PendingTransactions($chainId: Int!) {
  pendingTransaction(chainId: $chainId) {
    hash
    from
    to
    value
    gasPrice
  }
}

Resolver Architecture

DataLoader Pattern

Purpose: Prevent N+1 query problems.

Implementation:

  • Batch load related entities
  • Cache within request context
  • Example: Batch load all blocks for transactions in a query

Field Resolvers

Strategy: Lazy loading of related fields.

Example:

Block: {
  transactions: (block, args, context) => {
    return context.loaders.transactions.load({
      chainId: block.chainId,
      blockNumber: block.number
    });
  }
}

Performance Considerations

Query Complexity

Limits:

  • Max depth: 10 levels
  • Max complexity score: 1000
  • Rate limit based on complexity

Caching

Strategy:

  • Cache frequently accessed fields (blocks, tokens)
  • Cache duration: 1-60 seconds depending on data freshness needs
  • Invalidate on updates

Authentication

Same as REST API: API Key via header or OAuth Bearer token.

Error Handling

GraphQL Error Format:

{
  "errors": [
    {
      "message": "Resource not found",
      "extensions": {
        "code": "NOT_FOUND",
        "requestId": "uuid"
      },
      "path": ["block"]
    }
  ],
  "data": null
}

References

  • REST API: See rest-api.md
  • API Gateway: See api-gateway.md