Claude-skill-registry dojo-entities
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/dojo-entities" ~/.claude/skills/majiayu000-claude-skill-registry-dojo-entities && rm -rf "$T"
manifest:
skills/data/dojo-entities/SKILL.mdsource content
Dojo.js Entity Queries & Subscriptions
When to Use
Use this skill when:
- Fetching game entities from Torii
- Building queries with filters and pagination
- Subscribing to real-time entity updates
- Accessing model data in React components
ToriiQueryBuilder
Build type-safe queries for entities:
import { ToriiQueryBuilder, KeysClause, MemberClause } from "@dojoengine/sdk"; // Basic query with limit const query = new ToriiQueryBuilder<typeof schema>() .withLimit(100) .build(); // Query with clause filter const query = new ToriiQueryBuilder<typeof schema>() .withClause( KeysClause(["game-Player"], [playerAddress], "VariableLen").build() ) .withLimit(50) .build(); // Query with ordering const query = new ToriiQueryBuilder<typeof schema>() .addOrderBy("game-Player.score", "Desc") .withLimit(10) .build(); // Query specific models const query = new ToriiQueryBuilder<typeof schema>() .addEntityModel("game-Player") .addEntityModel("game-Position") .withLimit(100) .build();
Query Methods
Pagination
const query = new ToriiQueryBuilder<typeof schema>() .withLimit(50) // Max results .withCursor(nextCursor) // Pagination cursor .withDirection("Forward") // "Forward" | "Backward" .build();
Clause Types
// Keys clause - filter by entity keys KeysClause(["namespace-Model"], [key1, key2], "VariableLen") // Member clause - filter by field value MemberClause("namespace-Model", "fieldName", "Eq", value) // Composite clause - combine clauses CompositeClause("And", [clause1, clause2])
Fetching Entities
const { sdk } = useDojoSDK(); // One-time fetch const result = await sdk.getEntities({ query: new ToriiQueryBuilder<typeof schema>() .withClause(clause) .withLimit(100) }); // Access results result.items.forEach(entity => { console.log(entity.entityId, entity.models); }); // Pagination if (result.next_cursor) { const nextPage = await sdk.getEntities({ query: new ToriiQueryBuilder<typeof schema>() .withCursor(result.next_cursor) .withLimit(100) }); }
Subscribing to Entities
const { sdk } = useDojoSDK(); const [initialData, subscription] = await sdk.subscribeEntityQuery({ query: new ToriiQueryBuilder<typeof schema>() .withClause(clause) .withLimit(100), callback: ({ data, error }) => { if (error) { console.error("Subscription error:", error); return; } // Handle real-time updates console.log("Entity updated:", data); } }); // Clean up subscription subscription.cancel();
React Hooks
useModel - Single Entity Model
import { useModel } from "@dojoengine/sdk/react"; function PlayerStats({ entityId }) { // Format: "namespace-ModelName" const player = useModel(entityId, "game-Player"); if (!player) return <div>Loading...</div>; return <div>Score: {player.score}</div>; }
useModels - All Entities with Model
import { useModels } from "@dojoengine/sdk/react"; function Leaderboard() { const players = useModels("game-Player"); return ( <ul> {Object.entries(players).map(([entityId, player]) => ( <li key={entityId}>{player?.name}: {player?.score}</li> ))} </ul> ); }
useHistoricalModel - Time-series Data
import { useHistoricalModel } from "@dojoengine/sdk/react"; function PlayerHistory({ entityId }) { const history = useHistoricalModel(entityId, "game-Player"); return ( <ul> {history.map((snapshot, i) => ( <li key={i}>Score: {snapshot.models.game.Player.score}</li> ))} </ul> ); }
Entity ID Generation
import { getEntityIdFromKeys } from "@dojoengine/utils"; // Generate entity ID from keys const entityId = getEntityIdFromKeys([ BigInt(playerAddress), BigInt(gameId) ]);
Common Pitfalls
- Model name format: Use
format (hyphen-separated)"namespace-ModelName" - Entity ID type: Must be string, use
if neededentityId.toString() - Subscription cleanup: Always cancel subscriptions on component unmount
- Query limits: Default limit is 100, set explicit limits for large datasets