Get Started
Worker API
An event-driven indexer and API layer for Lightchain AI worker activity. It watches on-chain events, stores derived entities in PostgreSQL, and serves the indexed data through Express and GraphQL.Architecture Overview
At runtime, the service works like this:CodeTEXT
src/index.tsloads environment variables and the GraphQL schema.- A
Checkpointinstance is created withsrc/overrides.json. - The EVM indexers are registered.
- Checkpoint starts polling configured contracts.
- Express serves REST routes under
/apiand GraphQL at/.
What The Service Indexes
The current indexer watches three contracts:WorkerRegistryJobRegistryAIConfig
Contract addresses and start blocks are still hardcoded in src/evm/config.ts.
The repo ships with placeholder values and must be updated before real indexing will work.
Prerequisites
Before starting the service, make sure you have:- Bun
1.x - PostgreSQL
- an RPC endpoint for the intended Lightchain AI-compatible chain
package-lock.json.
Local Setup
1. Install dependencies
CodeBASH
2. Create your environment file
CodeBASH
CodeBASH
3. Update contract config
Before indexing real chain data, replace the placeholders insrc/evm/config.ts:
CONFIG.workerRegistryCONFIG.jobRegistryCONFIG.aiConfigCONFIG.workerRegistryStartCONFIG.jobRegistryStartCONFIG.aiConfigStart
4. Generate Checkpoint models
CodeBASH
.checkpoint/models/ from src/schema.gql.
5. Start the service
Development mode:CodeBASH
CodeBASH
Package Scripts
Indexed Event Coverage
WorkerRegistry
WorkerRegistered(address,bytes)WorkerDeregistered(address)ModelAdded(address,bytes32)ModelRemoved(address,bytes32)WorkerSlashed(address,uint256,uint256)WorkerJailed(address,uint256)WorkerUnjailed(address)StakeTopUp(address,uint256,uint256)ModelWhitelisted(bytes32)ModelDelisted(bytes32)
JobRegistry
SessionCreated(uint256,address,bytes32,address,bytes,bytes)SessionReassigned(uint256,address)JobSubmitted(uint256,uint256,address)JobAcknowledged(uint256,address)JobCompleted(uint256,address,bytes32[],bytes32)JobTimedOut(uint256,address,uint256)JobReleased(uint256,uint256,uint256,uint256)FeeDistributed(uint256,uint256,uint256,uint256)DisputeCreated(uint256,address)DisputeResolved(uint256,bool,uint256)WorkerWithdrawal(address,uint256)
AIConfig
ModelRegistered(bytes32,uint256,uint256,uint256)ModelEnabled(bytes32)ModelDisabled(bytes32)
Data Model
The GraphQL schema lives insrc/schema.gql.
Main entities:
Important identifier semantics:
Worker.idis the worker addressWorkerModel.idis${workerAddress}/${modelId}Job.idis the stringified on-chainjobIdSession.idis the stringified on-chainsessionIdNetworkStats.idis alwaysglobalSlashEvent.idis${txHash}/${logIndex}
REST API
GET /api/health
Returns:
CodeJSON
POST /api/workers/:address/online
Returns:
CodeJSON
- the request body is unused
- the route does not write to the database
- it simply calls
checkWorkerOnline(address)and returns the result
GraphQL Usage
Checkpoint mounts GraphQL at/.
Use src/schema.gql as the source of truth for available entity types, then inspect the live GraphQL schema after startup to see the generated root queries, filters, and pagination arguments.
In practice, the GraphQL API is centered on:
WorkerWorkerModelJobSessionSlashEventDisputeNetworkStatsModelInfo
Derived Behavior To Know About
Some values in the API are derived rather than directly stored on-chain.Worker status
The code derives worker status from:is_registeredis_jailedis_online
Slash correlation
The writer layer keeps an in-memory correlation map so aWorkerSlashed record can be linked to:
JobTimedOutDisputeResolved(workerGuilty = true)
null.
Global counters
NetworkStats is updated incrementally by handlers. It is not recomputed from scratch.
Known Caveats
These are current implementation realities:-
Online detection is stubbed.
src/evm/online-check.tscurrently returnstruefor every worker. -
Contract config is not environment-driven.
Addresses and start blocks are hardcoded in
src/evm/config.ts. -
WorkerModelremovals are not persisted as removals.handleModelRemovedupdates the worker timestamp, but does not delete or deactivate theWorkerModelrecord. -
Some
Jobfields are placeholders.escrowed_feeanddeadlineare initialized, but are not populated from indexed events in the current implementation. -
Session.statusis only partially modeled. Sessions are created as"Active"and are not fully transitioned through every on-chain state. - Slash correlation is in-memory. A process restart can break same-block correlation between related events.
- There is no committed test suite yet. Changes should be validated manually or covered with new tests.
The API is useful today, but it should be treated as an evolving indexer rather than a finalized production data contract.
Common Maintenance Tasks
Add a new indexed event
- Update the ABI under
src/evm/abisif needed. - Add the event mapping in
src/evm/config.ts. - Implement the writer in
src/evm/writers.ts. - If the schema changes, update
src/schema.gqland rerunbun run codegen.
Replace the online check
Implement the real availability logic insrc/evm/online-check.ts.
Current function contract:
CodeTYPESCRIPT
Move contract config to environment variables
If you want deployable environments without source edits:- Read contract addresses and start blocks from
process.env. - Extend
.env.example. - Validate those values near the top of
src/evm/config.ts.
Troubleshooting
.checkpoint/models is missing
Run:
CodeBASH
The service starts but no data appears
Check these first:RPC_URLpoints to the intended chain- the contract addresses are real
- the configured start blocks are correct
- PostgreSQL is reachable through
DATABASE_URL
REST works but GraphQL is empty
That usually means Express is healthy but the indexer is not ingesting events. In this repository, the most common causes are:- placeholder contract config
- RPC issues
- database connectivity issues
Related Guides
Last updated: March 2026