Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next #181

Merged
merged 4 commits into from
Jan 20, 2024
Merged

Next #181

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
21 changes: 21 additions & 0 deletions dojo-book/.gitignore
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
1 change: 1 addition & 0 deletions dojo-book/README.md
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.
23 changes: 23 additions & 0 deletions dojo-book/docs/pages/cairo/authorization.md
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.
79 changes: 79 additions & 0 deletions dojo-book/docs/pages/cairo/commands.md
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.
112 changes: 112 additions & 0 deletions dojo-book/docs/pages/cairo/events.md
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).
Loading
Loading