Skip to content

gRPC

TL;DR

  • gRPC is an efficient way to fetch your data
  • You can subscribe to entity and model events via the gRPC
  • Read more - gRPC

You can use the gRPC directly or you can use it through a developed client. A great way to use it is via dojo.js You can also check out the basic playground which showcases the simplest example of them all.

All the proto files can be found at : https://github.com/dojoengine/dojo/tree/main/crates/torii/grpc/proto. The proto files contains the definition of grpc server capacity.

Lexical Reference:

  • EntityId the entity id is the hash of the keys (including if there's only one key)
  • Member name is a member of a struct (Query.limit -> limit is the member name of query)

Query

Query type is basically used in either Retrieve or Subscribe grpc calls.

struct Query {
  /// This will be documented in next part
  clause: Clause,
  /// Max entities returned from query, useful for pagination
  limit: u32,
  /// Returned results offset, useful for pagination
  offset: u32,
  /// Wether you want torii to return internal EntityIds. If you want to know your entity ids and work with it you can set this to `false` otherwise, it will return hexadecimal index of the entity returned
  /// Performance wise, setting this to `true` is better as it will not have to compute the entity id.
  /// Note that for subscription, only KeysClause & HashedKeysClause are available for subscription queries.
  dont_include_hash_keys: bool,
  /// The way you want your entities to be ordered
  order_by: Vec<OrderBy>,
  /// Whitelist the models you want to retrieve. Torii will only include data of those models in response. For instance you can have one big entity that has $player as single key and dozens of models.
  /// For some display reasons in UI you may only want to get the content of your health model and use this to only get this specific value.
  entity_models: Vec<String>,
  /// Here you can set the latest timestamp of the query you've made. If you've cached some entities you may only want to retrieve those that have changed.
  entity_updated_after: u64,
}

Clause

This is the primitive to query you entities.

enum Clause {
  /// Query your entities based on keys (defined #[key] in your dojo models)
  EntityKeys: KeysClause,
  /// Internal torii entity ids.
  HashedKeys: HashedKeysClause,
  /// Query your entities based on their members values (for instance dojo_starter-Moves.remaining > 10)
  Member: MemberClause,
  /// Compose previous clause with "And" | "Or" logical operator to create those complex data fetching queries
  Composite: CompositeClause,
}
 
struct KeysClause {
  /// Keys values, you can use 'undefined' or an empty string as a wildcard to match any keys
  keys: Vec<String>,
  /// VariableLen: use it if you want at least `keys` matching your query
  /// FixedLen: use if you want keys to match exactly what you've passed in your query
  pattern_matching: "VariableLen" | "FixedLen",
  /// Model names that you want to query
  models: Vec<String>,
}
 
struct HashedKeysClause {
  /// Query over HashedKeys (which are EntityIds) returned by torii
  hashed_keys: Vec<String>
}
 
struct MemberClause {
  /// Model name you want to query
  model: String,
  /// Member name that you want to use as comparison
  member: String,
  /// How to query your model
  operator: ComparisonOperator,
  /// The value you want to compare
  value: MemberValue,
}
 
struct CompositeClause {
  /// List of clauses that you want to compose you can use nested Composite queries (if you want an extra spicy recipe)
  clauses: Vec<Clause>,
  /// How to match clauses
  operator: "Or" | "And",
}
 
 
enum MemberValue {
  /// Single string to compare
  String: String,
  /// Nested params to query over multiple values
  MemberValueList: Vec<MemberValue>
  /// Use primitive types for query
  Primitive: enum {
    i8: i8,
    i16: i16,
    i32: i32,
    i64: i64,
    i128: Vec<u8>,
    u8: u32,
    u16: u32,
    u32: u32,
    u64: u64,
    u128: Vec<u8>,
    u256: Vec<u8>,
    usize: u32,
    bool: bool,
    felt252: Vec<u8>,
    class_hash: Vec<u8>,
    contract_address: Vec<u8>,
  },
}
 
enum ComparisonOperator {
  Eq, Neq, Gt, Gte, Lt, Lte, In, NotIn
}

OrderBy

struct OrderBy {
  /// Model prefixed with namespace: "dojo_starter-Moves"
  model: String,
  /// Member key of the model passed as model : "remaining"
  member: String,
  /// Direction of the given results
  direction: "Asc" | "Desc",
}

Key-based Query

Get everything that has at least one key. Note that in dojo.js empty string uses 'undefined' as wildcard.

{
    "Keys": {
        "keys": [""],
        "pattern_matching": "VariableLen",
        "models": []
    }
}

Query entities that only have one key with a very specific value

{
    "Keys": {
        "keys": [
            "0x127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec"
        ],
        "pattern_matching": "FixedLen",
        "models": []
    }
}

Query entities that have at least "0x127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec" as the first key

{
    "Keys": {
        "keys": [
            "0x127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec"
        ],
        "pattern_matching": "VariableLen",
        "models": []
    }
}

Member-based Queries

Query players with more than 10 moves remaining:

{
    "Member": {
        "model": "dojo_starter-Moves",
        "member": "remaining",
        "operator": "Gt",
        "value": {
            "Primitive": {
                "U32": 10
            }
        }
    }
}

Query positions where x > 0:

{
    "Member": {
        "model": "dojo_starter-Position",
        "member": "x",
        "operator": "Gt",
        "value": {
            "Primitive": {
                "U32": 0
            }
        }
    }
}

Query active game states:

{
    "Member": {
        "model": "dojo_starter-GameState",
        "member": "active",
        "operator": "Eq",
        "value": {
            "Primitive": {
                "Bool": true
            }
        }
    }
}

Complex Queries

Composite AND/OR Query

Find active players within a specific area:

{
    "Composite": {
        "operator": "And",
        "clauses": [
            {
                "Member": {
                    "model": "dojo_starter-GameState",
                    "member": "active",
                    "operator": "Eq",
                    "value": {
                        "Primitive": {
                            "Bool": true
                        }
                    }
                }
            },
            {
                "Composite": {
                    "operator": "Or",
                    "clauses": [
                        {
                            "Member": {
                                "model": "dojo_starter-Position",
                                "member": "x",
                                "operator": "Gt",
                                "value": {
                                    "Primitive": {
                                        "U32": 0
                                    }
                                }
                            }
                        },
                        {
                            "Member": {
                                "model": "dojo_starter-Position",
                                "member": "y",
                                "operator": "Gt",
                                "value": {
                                    "Primitive": {
                                        "U32": 0
                                    }
                                }
                            }
                        }
                    ]
                }
            }
        ]
    }
}

Complete Query With All Options

Example of a complete query with pagination, ordering, and filtering:

{
    "limit": 10,
    "offset": 0,
    "clause": {
        "Member": {
            "model": "dojo_starter-Moves",
            "member": "remaining",
            "operator": "Gt",
            "value": {
                "Primitive": {
                    "U32": 0
                }
            }
        }
    },
    "dont_include_hashed_keys": false,
    "order_by": [
        {
            "model": "dojo_starter-Moves",
            "member": "remaining",
            "direction": "Desc"
        }
    ],
    "entity_models": ["dojo_starter-Moves"],
    "entity_updated_after": 0
}

Model-Specific Query Examples

Position Range Query

Query positions within a specific range:

{
    "Composite": {
        "operator": "And",
        "clauses": [
            {
                "Member": {
                    "model": "dojo_starter-Position",
                    "member": "x",
                    "operator": "Gte",
                    "value": {
                        "Primitive": {
                            "U32": 0
                        }
                    }
                }
            },
            {
                "Member": {
                    "model": "dojo_starter-Position",
                    "member": "y",
                    "operator": "Lt",
                    "value": {
                        "Primitive": {
                            "U32": 100
                        }
                    }
                }
            }
        ]
    }
}

Moves Query

Query for active players with available moves:

{
    "Composite": {
        "operator": "And",
        "clauses": [
            {
                "Member": {
                    "model": "dojo_starter-Moves",
                    "member": "remaining",
                    "operator": "Gt",
                    "value": {
                        "Primitive": {
                            "U32": 0
                        }
                    }
                }
            },
            {
                "Member": {
                    "model": "dojo_starter-Moves",
                    "member": "can_move",
                    "operator": "Eq",
                    "value": {
                        "Primitive": {
                            "Bool": true
                        }
                    }
                }
            }
        ]
    }
}

Common Query Patterns

Basic Pagination Query

{
    "limit": 25,
    "offset": 0,
    "clause": null,
    "dont_include_hashed_keys": false,
    "order_by": [],
    "entity_models": [],
    "entity_updated_after": 0
}

Model Filtering Query

{
    "limit": 100,
    "offset": 0,
    "clause": null,
    "dont_include_hashed_keys": false,
    "order_by": [],
    "entity_models": ["dojo_starter-Position", "dojo_starter-Moves"],
    "entity_updated_after": 0
}

Ordered Query

{
    "limit": 100,
    "offset": 0,
    "clause": null,
    "dont_include_hashed_keys": false,
    "order_by": [
        {
            "model": "dojo_starter-Moves",
            "member": "remaining",
            "direction": "Desc"
        }
    ],
    "entity_models": [],
    "entity_updated_after": 0
}