Skip to content

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 events.

What's even more exciting is that you can craft your own custom events to fit specific needs! Moreover, thanks to model's introspection and Torii, all these events are seamlessly indexed, ensuring easy and efficient 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.

There are two kind of Custom Events with different use-cases.

Using dojo::event

These events are acting like 'off-chain' storage and derive Model which allows Torii to easily parse them. Since it's a Model it must have a least a #[key] and any type used inside the model must derive Introspect.

For example we will declare a PlayerStatus struct to keep track of player mood.

  • We don't need this information on-chain.
  • We don't want to historize PlayerStatus changes, just keep track of the current/latest PlayerStatus.
#[derive(Copy, Drop, Introspect)]
struct Mood {
    Happy,
    Angry,
}
 
#[derive(Copy, Drop, Serde)]
#[dojo::model]
#[dojo::event]
struct PlayerMood {
    #[key]
    player: ContractAddress,
    mood: Mood,
 }

Emit the PlayerMood event:

emit!(world, (PlayerMood { player, mood: Mood::Happy }));

Each time a PlayerMood event is emitted, the PlayerMood Model indexed by Torii will reflect the lasted mood.

Using starknet::Event

These events are acting like classic starknet events, allowing historization.

Torii index this events in a raw format (ex : here).

Declare the starknet Event enum for you contract with a Moved variant:

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
    Moved: Moved,
}

Declare the Moved struct (you can have zero, one or more #[key]):

#[derive(Drop, Serde, starknet::Event)]
struct Moved {
    address: felt252,
    direction: felt252,
}

Emit the Moved event:

emit!(world, (Event::Moved( Moved { address, direction } )));

Example

Now a full example using a custom event:

fn move(world: IWorldDispatcher, direction: Direction) {
    let player = get_caller_address();
    let (mut position, mut moves) = get!(world, player, (Position, Moves));
 
    moves.remaining -= 1;
    moves.last_direction = direction;
    let next = next_position(position, direction);
 
    set!(world, (moves, next));
 
    emit!(world, (Event::Moved( Moved { player, direction } )));
}