dojo-indexer
Dojo 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:
entities- Access all entities with filteringmodels- Retrieve model definitionstransactions- Query indexed transactions
Model-Specific Queries:
{modelName}Models- Custom queries for each model- Example:
positionModels,movesModels
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 |
World contract address | Optional (since Torii 1.6.0) |
--rpc |
RPC endpoint URL | http://localhost:5050 |
--db-dir |
Database directory | In-memory |
--config |
Path to TOML configuration file | None |
--http.cors_origins |
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 (
dojo-clientskill) - 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
More from dojoengine/book
dojo-client
Integrate Dojo with game clients for JavaScript, Unity, Unreal, Rust, and other platforms. Generate typed bindings and connection code. Use when connecting frontends or game engines to your Dojo world.
69dojo-system
Create Dojo systems that implement game logic, modify model state, and handle player actions. Use when implementing game mechanics, player commands, or automated logic.
69dojo-migrate
Manage world migrations, handle breaking changes, and upgrade Dojo versions. Use when updating deployed worlds, migrating to new versions, or handling schema changes.
67dojo-test
Write tests for Dojo models and systems using spawn_test_world, cheat codes, and assertions. Use when testing game logic, verifying state changes, or ensuring system correctness.
67dojo-config
Configure Scarb.toml, dojo profiles, world settings, and dependencies. Use when setting up project configuration, managing dependencies, or configuring deployment environments.
66dojo-deploy
Deploy Dojo worlds to local Katana, testnet, or mainnet. Configure Katana sequencer and manage deployments with sozo. Use when deploying your game or starting local development environment.
66