-
Notifications
You must be signed in to change notification settings - Fork 87
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #181 from dojoengine/next
Next
- Loading branch information
Showing
357 changed files
with
10,266 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
|
||
# production | ||
/dist | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# typescript | ||
*.tsbuildinfo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
This is a [Vocs](https://vocs.dev) project bootstrapped with the Vocs CLI. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
## Authorization | ||
|
||
> Authorization is crucial to a world, just like how authorization is crucial to any smart contract. | ||
As discussed in the [World](./world.md) chapter, Autonomous Worlds (AWs) function as sovereign chains nested within a public blockchain. These Worlds are also open to the public. This structure allows anyone to enhance a World by deploying models or systems. However, this openness also introduces security considerations. Similar to Ethereum, interacting with a model's state within a System requires the appropriate authorization from the model owner. | ||
|
||
### Auth Architecture | ||
|
||
Every time a `set!` is called in a `System`, the world checks if the `System` has authorization to update the model state. Only when the `System` possesses the necessary authorization, the `set!` is executed. The following diagram illustrates the authorization architecture. | ||
|
||
![Authorization Architecture](/dojo-auth.png) | ||
|
||
### Providing Authorization | ||
|
||
> The deployer of the model is its initial owner. A model owner is able to grant the `owner` and `writer` roles. Only owners can grant a System the `writer` role which allows it to update the model. | ||
`sozo` offers a convenient tool to authorize systems. | ||
|
||
```shell | ||
sozo auth writer Moves spawn | ||
``` | ||
|
||
This command will generate a `writer` authorization for the `spawn` system to update the `Moves` model. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
## Commands | ||
|
||
**_TL;DR_** | ||
|
||
- Commands are shorthand ways to write function calls | ||
- Commands abstract complex queries into shorthands | ||
- Commands are similar to rust macros | ||
|
||
Understanding commands is key to understanding Dojo. You will leverage them heavily within the systems you design. | ||
|
||
Commands in Dojo are generalized functions that are expanded at compile time to facilitate system execution. They provide a convenient way for systems to interact with the world state by abstracting common operations, such as retrieving or updating models, and generating unique IDs. By leveraging these commands, developers can streamline their system implementations and improve code readability. | ||
|
||
### Using commands | ||
|
||
Commands are used within systems to interact with the world state. They are called using the following syntax: | ||
|
||
### The `get!` command | ||
|
||
The `get!` command is used to retrieve models from the world state: | ||
|
||
```rust,ignore | ||
// world = calling world | ||
// caller = key of the entity that called the system | ||
// (Position, Moves) = tuple of models to retrieve | ||
let (position, moves) = get!(world, caller, (Position, Moves)); | ||
``` | ||
|
||
Here we are retrieving the `Position` and `Moves` models from the world state. We are also using the `caller` to retrieve the models for the current entity. | ||
|
||
You can then use `position` and `moves` as you would as any other Cairo struct. | ||
|
||
In the case that your model defines several keys as the [resource example](./models.md#the-key-attribute), you must provide a value for each key. | ||
|
||
```rust,ignore | ||
let player = get_caller_address(); | ||
let location = 0x1234; | ||
let resource = get!(world, (player, location), (Resource)); | ||
``` | ||
|
||
If you use the `get!` command on a model that has never been set before, all the fields that are not `#[key]` are equal to 0 in the returned model, which is the default value in the storage. | ||
|
||
### The `set!` command | ||
|
||
The `set!` command is used to update models state. | ||
|
||
```rust,ignore | ||
set !(world, ( | ||
Moves { | ||
player: caller, remaining: 10 | ||
}, | ||
Position { | ||
player: caller, x: position.x + 10, y: position.y + 10 | ||
}, | ||
)); | ||
// If the structs are already defined it can also be written as: | ||
set!(world, (moves, position)); | ||
``` | ||
|
||
Here we are updating the `Moves` and `Position` models in the world state using the `caller` as the entity id. | ||
|
||
### The `emit!` command | ||
|
||
The `emit!` command is used to emit custom events. These events are indexed by [Torii](/toolchain/torii/overview.md). | ||
|
||
```rust,ignore | ||
emit!(world, Moved { address: caller, direction }); | ||
``` | ||
|
||
This will emit these values which could be captured by a client or you could query these via [Torii](/toolchain/torii/overview.md). | ||
|
||
### The `delete!` command | ||
|
||
The `delete!` command deletes a model from the db. | ||
|
||
```rust,ignore | ||
delete!(world, Moved { address: caller, direction }); | ||
``` |
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
## Events | ||
|
||
Events play a pivotal role in decoding the dynamics of a Dojo world. Every time there's an update to a `Model`, the `World` contract emits these events. What's even more exciting is that you can craft your own custom events to fit specific needs! Moreover, thanks to [Torii](/toolchain/torii/overview.md), all these events are seamlessly indexed, ensuring easy and efficient querying. | ||
|
||
### Model Events | ||
|
||
Consider this example of a `Moves` model: | ||
|
||
```rust,ignore | ||
struct Moves { | ||
#[key] | ||
player: Address, | ||
remaining: u32, | ||
} | ||
``` | ||
|
||
When this model is updated, the `World` contract will emit an event with the following structure: | ||
|
||
```rust,ignore | ||
#[derive(Drop, starknet::Event)] | ||
struct StoreSetRecord { | ||
table: felt252, // Moves | ||
keys: Span<felt252>, // [player] | ||
offset: u8, // offset for the value in the table | ||
value: Span<felt252>, // [remaining] | ||
} | ||
``` | ||
|
||
This will then be captured by [Torii](/toolchain/torii/overview.md) and indexed for querying. This will allow you to then reconstruct the state of your world. | ||
|
||
Similarly, when a model is deleted, the `World` contract will emit an event with the following structure: | ||
|
||
```rust,ignore | ||
#[derive(Drop, starknet::Event)] | ||
struct StoreDelRecord { | ||
table: felt252, | ||
keys: Span<felt252>, | ||
} | ||
``` | ||
|
||
### World Events | ||
|
||
The `World` contract also emits events when it's initialized and when new models and contracts are registered. These events are emitted with the following structures: | ||
|
||
```rust,ignore | ||
#[derive(Drop, starknet::Event)] | ||
struct WorldSpawned { | ||
address: ContractAddress, | ||
caller: ContractAddress | ||
} | ||
``` | ||
|
||
```rust,ignore | ||
#[derive(Drop, starknet::Event)] | ||
struct ModelRegistered { | ||
name: felt252, | ||
class_hash: ClassHash, | ||
prev_class_hash: ClassHash | ||
} | ||
``` | ||
|
||
```rust,ignore | ||
#[derive(Drop, starknet::Event)] | ||
struct ContractDeployed { | ||
salt: felt252, | ||
class_hash: ClassHash, | ||
address: ContractAddress, | ||
} | ||
#[derive(Drop, starknet::Event)] | ||
struct ContractUpgraded { | ||
class_hash: ClassHash, | ||
address: ContractAddress, | ||
} | ||
``` | ||
|
||
These events are also captured by [Torii](/toolchain/torii/overview.md) and indexed for querying. | ||
|
||
### Custom Events | ||
|
||
Within your game, emitting custom events can be highly beneficial. Fortunately, there's a handy `emit!` command that lets you release events directly from your world. These events are indexed by [Torii](/toolchain/torii/overview.md). | ||
|
||
Use it like so: | ||
|
||
```rust,ignore | ||
emit!(world, Moved { address, direction }); | ||
``` | ||
|
||
Include this in your contract and it will emit an event with the following structure: | ||
|
||
```rust,ignore | ||
#[derive(Drop, starknet::Event)] | ||
struct Moved { | ||
address: felt252, | ||
direction: felt252, | ||
} | ||
``` | ||
|
||
Now a full example using a custom event: | ||
|
||
```rust,ignore | ||
fn move(ctx: Context, direction: Direction) { | ||
let (mut position, mut moves) = get !(world, caller, (Position, Moves)); | ||
moves.remaining -= 1; | ||
let next = next_position(position, direction); | ||
set !(world, (moves, next)); | ||
emit !(world, Moved { address: caller, direction }); | ||
} | ||
``` | ||
|
||
> Note: Read about the `get!` and `set!` macros in [Commands](./commands.md). |
Oops, something went wrong.