352 lines
5.4 KiB
Markdown
352 lines
5.4 KiB
Markdown
# 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`
|
|
|