Awesome-omni-skill dojo-indexer
Set up and configure Torii indexer for GraphQL queries, gRPC subscriptions, and SQL access. Use when indexing your deployed world for client queries or real-time updates.
git clone https://github.com/diegosouzapw/awesome-omni-skill
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/dojo-indexer-majiayu000" ~/.claude/skills/diegosouzapw-awesome-omni-skill-dojo-indexer && rm -rf "$T"
skills/development/dojo-indexer-majiayu000/SKILL.mdDojo Indexer (Torii)
Set up and use Torii, the Dojo indexer, for efficient querying and real-time subscriptions to your world state.
When to Use This Skill
- "Set up Torii indexer"
- "Configure GraphQL for my world"
- "Create subscriptions for entity updates"
- "Query world state efficiently"
What This Skill Does
Manages Torii indexer:
- Start and configure Torii
- Create GraphQL queries
- Set up real-time subscriptions
- Access SQL database directly
Quick Start
Start Torii:
torii --world <WORLD_ADDRESS>
This starts Torii with default settings:
- GraphQL API at
http://localhost:8080/graphql - gRPC API at
http://localhost:8080 - In-memory database (for development)
With Controller indexing (recommended):
torii --world <WORLD_ADDRESS> --indexing.controllers
Production configuration:
torii --world <WORLD_ADDRESS> --db-dir ./torii-db --indexing.controllers
What is Torii?
Torii is the Dojo indexer that:
- Watches blockchain for world events
- Indexes model state changes
- Provides GraphQL API for queries
- Provides gRPC API for subscriptions
- Offers SQL access for complex queries
Why use Torii:
- Faster than direct RPC queries
- Complex queries (filters, pagination)
- Real-time subscriptions
- Type-safe GraphQL schema
GraphQL API
Torii provides GraphQL endpoint at
http://localhost:8080/graphql
Use the GraphiQL IDE in your browser to explore the schema and test queries.
Schema Structure
Torii generates two types of queries:
Generic Queries:
- Access all entities with filteringentities
- Retrieve model definitionsmodels
- Query indexed transactionstransactions
Model-Specific Queries:
- Custom queries for each model{modelName}Models- Example:
,positionModelsmovesModels
Basic Queries
Get all entities of a model:
query { movesModels { edges { node { player remaining last_direction } } } }
Get model metadata:
query { models { edges { node { id name classHash contractAddress } } totalCount } }
Pagination
Cursor-based pagination:
query { entities(first: 10) { edges { cursor node { id } } pageInfo { hasNextPage endCursor } } }
Get next page:
query { entities(first: 10, after: "cursor_value") { edges { cursor node { id } } } }
Offset/limit pagination:
query { entities(offset: 20, limit: 10) { edges { node { id } } totalCount } }
Real-time Subscriptions
Subscribe to world state changes via WebSocket.
Entity Updates
subscription { entityUpdated(id: "0x54f58...") { id updatedAt models { __typename ... on Position { vec { x y } } ... on Moves { remaining } } } }
Event Stream
Monitor all world events:
subscription { eventEmitted { id keys data transactionHash } }
Model Registration
Listen for new model registrations:
subscription { modelRegistered { id name namespace } }
SQL Access
Torii stores data in SQLite, accessible for complex queries.
Connect to database:
sqlite3 torii.db
Example queries:
-- Count entities SELECT COUNT(*) FROM entities; -- Custom aggregations SELECT AVG(value) FROM model_data WHERE model_name = 'Health';
Client Integration
JavaScript/TypeScript
import { createClient } from '@dojoengine/torii-client'; const client = await createClient({ rpcUrl: "http://localhost:5050", toriiUrl: "http://localhost:8080", worldAddress: WORLD_ADDRESS, }); // Query entities const positions = await client.getEntities({ model: "Position", limit: 10 }); // Subscribe to updates await client.onEntityUpdated( [{ model: "Position", keys: [playerId] }], (entity) => console.log("Position updated:", entity) );
Apollo Client (GraphQL)
import { ApolloClient, InMemoryCache, gql } from '@apollo/client'; const client = new ApolloClient({ uri: 'http://localhost:8080/graphql', cache: new InMemoryCache(), }); const { data } = await client.query({ query: gql` query GetMoves { movesModels { edges { node { player remaining } } } } ` });
Configuration Options
| Option | Description | Default |
|---|---|---|
| World contract address | Optional (since Torii 1.6.0) |
| RPC endpoint URL | |
| Database directory | In-memory |
| Path to TOML configuration file | None |
| CORS origins | |
Slot Deployment (Remote)
Slot provides hosted Torii instances. Slot requires a TOML configuration file.
Create Configuration
# torii.toml world_address = "<WORLD_ADDRESS>" rpc = "<RPC_URL>" [indexing] controllers = true
See the Torii configuration guide for all TOML options (indexing, polling, namespaces, etc.).
Deploy
slot auth login slot deployments create <PROJECT_NAME> torii --config torii.toml --version <DOJO_VERSION>
Manage
# Stream logs slot deployments logs <PROJECT_NAME> torii -f # Delete and recreate (safe — all data is on-chain) slot deployments delete <PROJECT_NAME> torii
Development Workflow
Terminal 1: Start Katana
katana --dev --dev.no-fee
Terminal 2: Deploy world
sozo build && sozo migrate
Terminal 3: Start Torii
torii --world <WORLD_ADDRESS> --http.cors_origins "*"
Troubleshooting
"Connection refused"
- Check Torii is running
- Verify port (default 8080)
- Check firewall rules
"World not found"
- Verify world address is correct
- Check RPC URL is accessible
- Ensure world is deployed
"Slow queries"
- Use model-specific queries instead of generic
entities - Use pagination
- Request only needed fields
Next Steps
After Torii setup:
- Integrate with client (
skill)dojo-client - Create optimized queries
- Set up subscriptions
- Monitor performance
Related Skills
- dojo-deploy: Deploy world first
- dojo-client: Use Torii in clients
- dojo-world: Configure what Torii indexes
- dojo-migrate: Restart Torii after migrations