A high-performance blockchain indexer for Kleros Generalized Token Curated Registries (GTCR). This indexer tracks and indexes all GTCR-related events across multiple networks, providing a comprehensive GraphQL API for querying registry data, items, requests, disputes, and evidence.
The GTCR Indexer monitors and indexes events from Kleros GTCR contracts, including both classic GeneralizedTCR and LightGeneralizedTCR implementations. It provides real-time indexing of:
- Registry Management: Factory deployments and registry configurations
- Item Lifecycle: Submissions, status changes, and metadata
- Dispute Resolution: Arbitration processes, appeals, and rulings
- Evidence Handling: IPFS-based evidence submission and retrieval
- Financial Tracking: Deposits, contributions, and reward distributions
- 🚀 Multi-chain Support: Ethereum Mainnet, Gnosis Chain, and Sepolia testnet
- 📊 Real-time Indexing: Live event processing with sub-second latency
- 🔍 Rich GraphQL API: Comprehensive querying capabilities with relationships
- 📁 IPFS Integration: Automatic metadata and evidence fetching from IPFS
- 🏗️ Type Safety: Full TypeScript implementation with generated types
- 🔄 Unordered Multichain: Efficient cross-chain event processing
- 📈 Performance Optimized: Built for high-throughput blockchain data
Network | Chain ID | Start Block | Contracts |
---|---|---|---|
Ethereum Mainnet | 1 | 10,247,117 | GTCRFactory, LightGTCRFactory |
Gnosis Chain | 100 | 16,969,180 | GTCRFactory, LightGTCRFactory |
Sepolia Testnet | 11155111 | 4,048,282 | GTCRFactory, LightGTCRFactory |
- Node.js (v18 or newer)
- pnpm (v8 or newer)
- Docker Desktop
-
Clone the repository
git clone https://github.com/kleros/gtcr-indexer.git cd gtcr-indexer
-
Install dependencies
pnpm install
-
Set up environment variables
cp .env.example .env
Edit
.env
and configure:ENVIO_API_TOKEN="your-envio-api-token" ENVIO_GNOSIS_RPC_URL="https://rpc.gnosis.gateway.fm" ENVIO_MAINNET_RPC_URL="https://eth-mainnet.g.alchemy.com/v2/your-key" ENVIO_SEPOLIA_RPC_URL="https://eth-sepolia.g.alchemy.com/v2/your-key"
-
Generate code from schema
pnpm codegen
-
Start the indexer
pnpm dev
-
Access GraphQL Playground
Visit http://localhost:8080 (password:
testing
)
The indexer supports two main GTCR implementations:
- Full-featured registry with comprehensive dispute resolution
- Supports complex appeal mechanisms and contribution tracking
- Used for high-stakes registries requiring maximum security
- Streamlined implementation with reduced gas costs
- Simplified dispute resolution process
- Optimized for frequent interactions and lower-value items
The indexer maintains a comprehensive data model including:
- Registries: GTCR contract instances with metadata
- Items: Individual entries in registries with status tracking
- Requests: Status change requests (registration/removal)
- Disputes: Arbitration cases with round-based appeals
- Evidence: IPFS-linked evidence submissions
- Contributions: Financial contributions to dispute sides
The indexer processes the following key events:
Event | Description | Contracts |
---|---|---|
NewGTCR |
New registry deployment | Factory contracts |
ItemStatusChange |
Item status updates | GTCR contracts |
Evidence |
Evidence submission | GTCR contracts |
Dispute |
Dispute creation | GTCR contracts |
Ruling |
Arbitrator decisions | GTCR contracts |
Contribution |
Appeal contributions | GTCR contracts |
query GetRegistries {
Registry {
id
numberOfItems
connectedTCR
registrationMetaEvidence {
uri
}
}
}
query GetItems($registryId: String!) {
Item(where: { registry_id: { _eq: $registryId } }) {
id
itemID
status
disputed
latestRequester
numberOfRequests
}
}
query GetEvidence($evidenceGroupId: String!) {
EvidenceGroup_by_pk(id: $evidenceGroupId) {
evidences {
id
party
uri
title
description
timestamp
}
}
}
query GetDispute($itemId: String!) {
Item_by_pk(id: $itemId) {
requests {
disputed
disputeOutcome
rounds {
ruling
amountPaidRequester
amountPaidChallenger
appealed
}
}
}
}
src/
├── constants/ # Chain configurations and constants
├── mappings/ # Event handlers organized by contract
│ ├── GTCRFactoryMappings/ # Factory contract handlers
│ ├── GTCRMappings/ # Classic GTCR handlers
│ ├── LightGTCRFactoryMappings/ # Light factory handlers
│ ├── LightGTCRMappings/ # Light GTCR handlers
│ └── helpers/ # Shared mapping utilities
└── utils/ # Utility functions
├── contract/ # Contract interaction utilities
└── ipfs/ # IPFS data fetching
# Development
pnpm dev # Start development server with hot reload
pnpm start # Start production server
pnpm stop # Stop the indexer
# Code Generation
pnpm codegen # Generate types from schema and config
# Building
pnpm build # Compile TypeScript
pnpm clean # Clean build artifacts
# Testing
pnpm test # Run test suite
pnpm mocha # Run mocha tests directly
-
Define the event in
config.yaml
events: - event: YourEvent(address indexed param1, uint256 param2)
-
Create the handler file
// src/mappings/YourContract/YourEvent.ts import { YourContract } from "generated"; YourContract.YourEvent.handler(async ({ event, context }) => { // Handle the event });
-
Export the handler
// src/mappings/YourContract/index.ts import "./YourEvent";
-
Regenerate types
pnpm codegen
The indexer automatically fetches and parses metadata from IPFS:
- Registry Metadata: Title, description, item naming
- Evidence Data: Evidence files with titles and descriptions
- Item Data: Structured item information based on registry schema
IPFS fetching is handled through Envio's effect system with automatic caching and error handling.
Variable | Description | Required |
---|---|---|
ENVIO_API_TOKEN |
Envio platform API token | Yes |
ENVIO_GNOSIS_RPC_URL |
Gnosis Chain RPC endpoint | Yes |
ENVIO_MAINNET_RPC_URL |
Ethereum Mainnet RPC endpoint | Yes |
ENVIO_SEPOLIA_RPC_URL |
Sepolia testnet RPC endpoint | Yes |
ENVIO_KLEROS_CDN_LINK |
Kleros CDN for metadata | Yes |
Networks are configured in config.yaml
with specific contract addresses and start blocks. The indexer uses unordered_multichain_mode
for efficient cross-chain processing.
-
Set up environment variables
export ENVIO_API_TOKEN="your-production-token" export ENVIO_GNOSIS_RPC_URL="your-production-rpc" # ... other variables
-
Build the project
pnpm build
-
Start the indexer
pnpm start
- Fork the repository
- Create a feature branch
git checkout -b feature/your-feature-name
- Make your changes
- Add tests if applicable
- Submit a pull request
- Use TypeScript for all new code
- Follow existing naming conventions
- Add JSDoc comments for public functions
- Ensure type safety throughout
For questions and support: