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