# 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

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

#### Transaction

```graphql
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

```graphql
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

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

#### Contract

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

## Queries

### Block Queries

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

### Transaction Queries

```graphql
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

```graphql
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

```graphql
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

```graphql
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

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

## Subscriptions

### New Blocks

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

### Address Transactions

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

### Pending Transactions

```graphql
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**:
```javascript
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**:
```json
{
  "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`

