Skip to content

Commit

Permalink
Merge pull request #106 from dojoengine/gianm-update
Browse files Browse the repository at this point in the history
Update book content
  • Loading branch information
ponderingdemocritus authored Nov 20, 2023
2 parents 7ce7a89 + 775b54a commit 62b37b8
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 96 deletions.
2 changes: 1 addition & 1 deletion src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ This book is dedicated to familiarizing you with the Dojo engine and the potenti

- [Quickstart](./getting-started/quick-start.md)
- [What is Dojo? ](./theory/what-is-dojo.md)
- [Explore the Architecture](./cairo/hello-dojo.md)
- [Explore the Architecture](./cairo/overview.md)


### Explainer
Expand Down
42 changes: 5 additions & 37 deletions src/cairo/entities.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
## Entities

> Entities are the primary key value within the world, to which components can be attached.
> Entities are the primary key value within the world, to which models can be attached.
Different ECS systems handle entities in various ways. In Dojo, entities are treated as a primary key value within the world, to which components can be attached. To illustrate this concept, consider a simple example of a character in a game that has a `Moves` and a `Position` component.
Different ECS systems handle entities in various ways. In Dojo, entities are treated as a primary key value within the world, to which models can be attached. To illustrate this concept, consider a simple example of a character in a game that has a `Moves` and a `Position` model.

When defining the components for this entity, it is important to note that we do not reference the entity directly. Instead, we simply provide two structs that the entity will contain.
When defining the models for this entity, it is important to note that we do not reference the entity directly. Instead, we simply provide two structs that the entity will contain.

```rust,ignore
#[derive(Component, Copy, Drop, Serde, SerdeLen)]
#[derive(Models, Drop, Serde)]
struct Moves {
#[key]
player: ContractAddress,
remaining: u8,
}
#[derive(Component, Copy, Drop, Serde, SerdeLen)]
#[derive(Models, Drop, Serde)]
struct Health {
#[key]
player: ContractAddress,
Expand All @@ -23,36 +23,4 @@ struct Health {
}
```

Now, let's create a `Spawn` for the character. It is important to note that we have not explicitly defined an Entity anywhere. Instead, we use the `ctx.origin` to reference the current entity.

In this example we are using the `ctx.origin` to reference the current entity.

```rust,ignore
#[system]
mod spawn {
use array::ArrayTrait;
use box::BoxTrait;
use traits::Into;
use dojo::world::Context;
use dojo_examples::components::Position;
use dojo_examples::components::Moves;
fn execute(ctx: Context) {
let position = get!(ctx.world, ctx.origin, (Position));
set!(
ctx.world,
(
Moves {
player: ctx.origin, remaining: 10
}, Position {
player: ctx.origin, x: position.x + 10, y: position.y + 10
},
)
);
return ();
}
}
```

> ECS Theory: Plenty has been written on ECS systems, to go deeper read [ECS-FAQ](https://github.com/SanderMertens/ecs-faq)
6 changes: 3 additions & 3 deletions src/cairo/hello-dojo.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,16 +261,16 @@ Your 🌎 is now deployed at `0x1af130f7b9027f3748c1e3b10ca4a82ac836a30ac4f2f840

This establishes the world address for your project.

Let's discuss the `Scarb.toml` file in the project. This file contains environment variables that make running CLI commands in your project a breeze. (Read more about it [here](./config.md)). Make sure your file specifies the version of Dojo you have installed!. In this case version `v0.3.1`
Let's discuss the `Scarb.toml` file in the project. This file contains environment variables that make running CLI commands in your project a breeze. (Read more about it [here](./config.md)). Make sure your file specifies the version of Dojo you have installed!. In this case version `0.3.10`

```toml
[dependencies]
dojo = { git = "https://github.com/dojoengine/dojo", rev = "v0.3.1" }
dojo = { git = "https://github.com/dojoengine/dojo", version = "0.3.10" }
```

### Indexing

With your local world address established, let's delve into indexing. You can index the entire world. Open a new terminal and input this simple command:
With your local world address established, let's delve into indexing. You can index the entire world. To accomplish this we have to copy your world address from the output of `sozo migrate`. Now Open a new terminal and input this simple command that includes your own world address:

```bash
torii --world 0x1af130f7b9027f3748c1e3b10ca4a82ac836a30ac4f2f84025e83a99a922a0c
Expand Down
23 changes: 8 additions & 15 deletions src/cairo/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,18 @@ While seemingly simple, behind the scenes Dojo generates foundational contracts,
Lets take a look at the `main.cairo`:

```rust,ignore
use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait};
use starknet::ContractAddress;
// dojo data models
#[derive(Model, Copy, Drop, Print, Serde)]
#[derive(Model, Copy, Drop, Serde)]
struct Position {
#[key] // primary key
player: ContractAddress,
vec: Vec2,
}
// regular cairo struct
#[derive(Copy, Drop, Serde, Print, Introspect)]
#[derive(Copy, Drop, Serde, Introspect)]
struct Vec2 {
x: u32,
y: u32
Expand All @@ -43,28 +42,26 @@ struct Vec2 {
// interface
#[starknet::interface]
trait IPlayerActions<TContractState> {
fn spawn(self: @TContractState, world: IWorldDispatcher);
fn spawn(self: @TContractState);
}
// contract
#[starknet::contract]
#[dojo::contract]
mod player_actions {
use starknet::{ContractAddress, get_caller_address};
use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait};
use super::{Position, Vec2};
use super::IPlayerActions;
// note the is no storage here - it's in the world contract
#[storage]
struct Storage {}
#[external(v0)]
impl PlayerActionsImpl of IPlayerActions<ContractState> {
//
// NOTICE: we pass the world dispatcher as an argument to every function.
// This is how we interact with the world contract.
//
fn spawn(self: @ContractState, world: IWorldDispatcher) {
fn spawn(self: @ContractState) {
// Access the world dispatcher for reading.
let world = self.world_dispatcher.read();
// get player address
let player = get_caller_address();
Expand Down Expand Up @@ -94,10 +91,6 @@ In the `spawn` function, take note of the second parameter: the `IWorldDispatche

Commands, a significant innovation in Dojo, are further explored [here](./commands.md).

#### `#[storage]` attribute

You will notice there is no storage in the contract. This is because the storage is in the world contract. You can however use this attribute to store data in the System contract itself, but we suggest you use the world contract for storage.

### High level transaction flow of a world

To call a Dojo world you invoke a system, which then calls the [world](./world.md) and does the necessary state changes.
Expand Down
59 changes: 24 additions & 35 deletions src/cairo/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,25 @@ Lets show a `model` test example from the [dojo-starter](https://github.com/dojo
`models.cairo`
```rust,ignore
...rest of code
...//rest of code
#[cfg(test)]
mod tests {
use debug::PrintTrait;
use super::{Position, PositionTrait};
use super::{Position, Vec2, Vec2Trait};
#[test]
#[available_gas(100000)]
fn test_position_is_zero() {
let player = starknet::contract_address_const::<0x0>();
assert(PositionTrait::is_zero(Position { player, x: 0, y: 0 }), 'not zero');
fn test_vec_is_zero() {
assert(Vec2Trait::is_zero(Vec2 { x: 0, y: 0 }), 'not zero');
}
#[test]
#[available_gas(100000)]
fn test_position_is_equal() {
let player = starknet::contract_address_const::<0x0>();
let position = Position { player, x: 420, y: 0 };
position.print();
assert(PositionTrait::is_equal(position, Position { player, x: 420, y: 0 }), 'not equal');
fn test_vec_is_equal() {
let position = Vec2 { x: 420, y: 0 };
assert(position.is_equal(Vec2 { x: 420, y: 0 }), 'not equal');
}
}
```

In this test we are testing the `is_zero` and `is_equal` functions of the `Position` model. It is good practise to test all functions of your models.
Expand All @@ -64,21 +59,11 @@ mod tests {
use dojo_examples::models::{position, moves};
use dojo_examples::models::{Position, Moves, Direction};
use super::{
IPlayerActionsDispatcher, IPlayerActionsDispatcherTrait,
player_actions_external as player_actions
};
//OFFSET is defined in constants.cairo
use dojo_examples::constants::OFFSET;
//{Event and Moved are defined in events.cairo}
#[event]
use dojo_examples::events::{Event, Moved};
use super::{actions, IActionsDispatcher, IActionsDispatcherTrait};
// helper setup function
// reusable function for tests
fn setup_world() -> IPlayerActionsDispatcher {
fn setup_world() -> IActionsDispatcher {
// components
let mut models = array![position::TEST_CLASS_HASH, moves::TEST_CLASS_HASH];
Expand All @@ -87,10 +72,10 @@ mod tests {
// deploy systems contract
let contract_address = world
.deploy_contract('salt', player_actions::TEST_CLASS_HASH.try_into().unwrap());
let player_actions_system = IPlayerActionsDispatcher { contract_address };
.deploy_contract('salt', actions::TEST_CLASS_HASH.try_into().unwrap());
let actions_system = IActionsDispatcher { contract_address };
player_actions_system
actions_system
}
Expand All @@ -100,24 +85,28 @@ mod tests {
// caller
let caller = starknet::contract_address_const::<0x0>();
let player_actions_system = setup_world();
let actions_system = setup_world();
// System calls
player_actions_system.spawn();
player_actions_system.move(Direction::Right(()));
actions_system.spawn();
actions_system.move(Direction::Right(()));
// check moves
let moves = get!(world, caller, (Moves));
assert(moves.remaining == 99, 'moves is wrong');
// check position
let new_position = get!(world, caller, (Position));
assert(new_position.x == (OFFSET + 1).try_into().unwrap(), 'position x is wrong');
assert(new_position.y == OFFSET.try_into().unwrap(), 'position y is wrong');
// get new_position
let new_position = get!(world, caller, Position);
// check new position x
assert(new_position.vec.x == 11, 'position x is wrong');
// check new position y
assert(new_position.vec.y == 10, 'position y is wrong');
}
}
```

#### Useful Dojo Test Functions

`spawn_test_world(models, systems)` - This function will create a test world with the models and systems you pass in. It will also deploy the world and register the models and systems.
`spawn_test_world(models)` - This function will create a test world with the models and systems you pass in. It will also deploy the world and register the models and systems.
4 changes: 2 additions & 2 deletions src/theory/cairo.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Provable games

Provable games demand [zero-knowledge](https://ethereum.org/en/zero-knowledge-proofs/) properties for efficient scaling and verification of computations. [Cairo](https://book.starknet.io/chapter_1/what_is_cairo.html) addresses this need by providing a generalized language, eliminating the complexity of creating circuits to incorporate [SNARKs](https://consensys.net/blog/developers/introduction-to-zk-snarks/).
Provable games demand [zero-knowledge](https://ethereum.org/en/zero-knowledge-proofs/) properties for efficient scaling and verification of computations. [Cairo](https://book.starknet.io/ch01-00-getting-started.html) addresses this need by providing a generalized language, eliminating the complexity of creating circuits to incorporate [SNARKs](https://consensys.net/blog/developers/introduction-to-zk-snarks/).

**You can simply program in Cairo and your applications become automatically provable**.

Expand All @@ -19,7 +19,7 @@ A key feature of the Dojo framework is its use of [commands](../cairo/commands.m
Developers can write commands freely within Systems, and the Cairo compiler takes care of inlining the appropriate functions.

#### Essential Reading
- [Cairo book](https://cairo-book.github.io/)
- [Cairo book](https://github.com/cairo-book/cairo-book)
- [Awesome Cairo](https://github.com/auditless/awesome-cairo)
- [Starknet Book](https://book.starknet.io/)

Expand Down
2 changes: 1 addition & 1 deletion src/theory/what-is-dojo.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Read detailed information about the [Dojo ECS](../cairo/overview.md).

### [Torii](/crates/torii/README.md) - Starknet Indexer

Building on-chain games often involves grappling with the challenge of indexing on-chain state. However, Dojo standardizes contract states to mirror traditional relational databases. This setup enables the [Torii Indexer](../toolchain/torii/overview.md) to auto-index all contract states, ensuring efficient and streamlined queries. Torii then exposes these states via a GraphQL API or gRPC (coming soon), allowing developers to easily query and retrieve data.
Building on-chain games often involves grappling with the challenge of indexing on-chain state. However, Dojo standardizes contract states to mirror traditional relational databases. This setup enables the [Torii Indexer](../toolchain/torii/overview.md) to auto-index all contract states, ensuring efficient and streamlined queries. Torii then exposes these states via a GraphQL API or gRPC, allowing developers to easily query and retrieve data.

Using Torii drastically reduces the time and effort required to build on-chain games. It also eliminates the need to manually create indexers, which can be a tedious and error-prone process.

Expand Down
6 changes: 4 additions & 2 deletions src/toolchain/katana/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ cargo install --path ./crates/katana --locked --force
### Usage

```console
$ katana
katana
```

```
██╗ ██╗ █████╗ ████████╗ █████╗ ███╗ ██╗ █████╗
Expand Down Expand Up @@ -57,7 +59,7 @@ ACCOUNTS SEED
0
🚀 JSON-RPC server started: http://127.0.0.1:5050
🚀 JSON-RPC server started: http://0.0.0.0:5050
```
Expand Down

0 comments on commit 62b37b8

Please sign in to comment.