dojoengine / dojo

Dojo is a toolchain for building provable games and autonomous worlds with Cairo
https://dojoengine.org
Apache License 2.0
408 stars 165 forks source link

[BUG] Torii starknet::events are not identifiable or queryable #1873

Closed rsodre closed 5 months ago

rsodre commented 5 months ago

Describe the bug

The Dojo Book talks about two kinds of Custom Events:

The first uses dojo::event https://book.dojoengine.org/cairo/events#with-dojoevent

Since it's a Model it must have a least a #[key] For example we will declare a PlayerStatus struct to keep track of player mood. We don't want to historize PlayerMood changes, just keep track of the current/latest PlayerMood

The second kind uses starknet::event https://book.dojoengine.org/cairo/events#with-starknetevent

This events are acting like classic starknet events, allowing historization. It does not require a key, as an event with the same data can happen multiple times, and we may want to register and know about every time it was emitted.

But currently (Dojo 0.6.1-alpha3), there is no way to query or identify a starknet::event event.

I understand we could just catch everything using dojo::event, and filter the events I want from their data... but it is a lot of unnecessary work. starknet::event` has its usefulness, and is really simple to use. Also, it is what any web3 developer thinks when we talk about events, that's how Ethereum and Starknet events work.

To Reproduce

There was a starknet event in dojo-starter but it was removed.

On my game, I declared and emitted this event, just like in the Book:

#[derive(Drop, starknet::Event)]
struct DuelistTurnEvent {
    duel_id: u128,
    duelist_address: ContractAddress,
    round_number: u8,
}

// inside #[dojo::contract]

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

emit!(world, events::DuelistTurnEvent {
    duel_id: 0x111,
    duelist_address: starknet::contract_address_const::<0x222>(),
    round_number: 0xff,
});

The only way to catch this event is to create a generic query like this, exactly as suggested in the Book:

subscription {
  eventEmitted {
    id
    keys
    data
    transactionHash
  }
}

From all the events the the game generates, I could only identify it because I emitted very specific values that I could pick:

  "data": {
    "eventEmitted": {
      "id": "0x0000000000000000000000000000000000000000000000000000000000001f:0x2f22a8d6f7468cee16032cf54611db99297cc2b497cdbc2e476db7ef34bbb0a:0x00",
      "keys": [
        "0x702e255a3446fce9c49df1c579a62fba9e6bfefd4621a437b28c559b68e0f81"
      ],
      "data": [
        "0x111",
        "0x222",
        "0xff"
      ],
      "transactionHash": "0x2f22a8d6f7468cee16032cf54611db99297cc2b497cdbc2e476db7ef34bbb0a"
    }
  }
}

What's inside...

id: Looks like it is a combination of sequential numbers and the transaction hash keys: This is the address of my system data: The data emitted by the event transactionHash: exactly that, no use here

Problem 1: The event name, nor even its hash, is not here, it's impossible to find a DuelistTurnEvent from the events feed. Problem 2: It is impossible to create a query to subscribe to a DuelistTurnEvent.

Expected behavior

I expect 2 things from events, that as far as I know are impossible right now:

I suggest adding a name field containing the event name to World__Event...

rsodre commented 5 months ago

@notV4l just pointed out that I was emitting wrong. the correct way is:

emit!(world, (Event::DuelistTurnEvent( events::DuelistTurnEvent {
    duel_id: 0x111,
    duelist_address: starknet::contract_address_const::<0x222>(),
    round_number: 0xff,
})));

now I have the selector name in the emitted event keys, and can find and query...

{
  "data": {
    "eventEmitted": {
      "id": "0x00000000000000000000000000000000000000000000000000000000000020:0x76d2101240a2887d6a4757ee972ec89ec867defe3a60a13023d476c162e285:0x00",
      "keys": [
        "0x19556e1418f1e7a7e6962eff75d1a46abd50bda431139f855ba85c9119754a4",
        "0x702e255a3446fce9c49df1c579a62fba9e6bfefd4621a437b28c559b68e0f81"
      ],
      "data": [
        "0x111",
        "0x222",
        "0xff"
      ],
      "transactionHash": "0x76d2101240a2887d6a4757ee972ec89ec867defe3a60a13023d476c162e285"
    }
  }
}

and I didn't know about this...

$ starkli selector DuelistTurnEvent
0x019556e1418f1e7a7e6962eff75d1a46abd50bda431139f855ba85c9119754a4

closing it, doesn't look like a problem anymore