# Is it possible to fetch by type?

**URL:** <https://forums.sui.io/t/is-it-possible-to-fetch-by-type/2316>\
**Category:** Technical Support\
**Tags:** sui\
**Created:** [January 11, 2023, 11:12pm UTC](https://forums.sui.io/t/is-it-possible-to-fetch-by-type/2316 "2023-01-11T23:12:41Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![PauwCrypto](https://dub1.discourse-cdn.com/sui/user_avatar/forums.sui.io/pauwcrypto/32/1188_2.png) [@PauwCrypto](https://forums.sui.io/u/PauwCrypto)\
**Post date:** [January 11, 2023, 11:12pm UTC](https://forums.sui.io/t/is-it-possible-to-fetch-by-type/2316/1 "2023-01-11T23:12:41Z")

</div>

Hi all,

I recently deployed the shared\_tic\_tac\_toe.move example and am builing a FE around it. The game awards the winner of the match with a Trophy object. Is it possible to fetch all objects by type? This way I could create a leaderboard with how many trophies each address has won.

The type looks as follows on the sui explorer:  
[packageAddress]::shared\_tic\_tac\_toe::Trophy

However I do not see a type field in the possible arguments within the Sui TS SDK functions. Anyone know if this is possible?

---

<div class="post-metadata">

**Author:** ![amnn](https://dub1.discourse-cdn.com/sui/user_avatar/forums.sui.io/amnn/32/25_2.png) [@amnn](https://forums.sui.io/u/amnn)\
**Post date:** [January 12, 2023, 11:56am UTC](https://forums.sui.io/t/is-it-possible-to-fetch-by-type/2316/2 "2023-01-12T11:56:41Z")

</div>

We don’t currently index all objects by type, but if you want to support this kind of functionality, I would recommend using the Events system:

- When a user wins a trophy, [emit an event](https://github.com/MystenLabs/sui/blob/main/doc/book/examples/sources/basics/events.move#L70) from the contract containing the ID of their Trophy.
- Use the `sui_getEvents` RPC, which [supports querying for events by type](https://docs.sui.io/devnet/build/event_api#sui-event-query-criteria), to get the full list of events from users winning in your tic-tac-toe game.

---

<div class="post-metadata">

**Author:** ![PauwCrypto](https://dub1.discourse-cdn.com/sui/user_avatar/forums.sui.io/pauwcrypto/32/1188_2.png) [@PauwCrypto](https://forums.sui.io/u/PauwCrypto)\
**Post date:** [January 12, 2023, 1:24pm UTC](https://forums.sui.io/t/is-it-possible-to-fetch-by-type/2316/3 "2023-01-12T13:24:19Z")

</div>

Got it, thanks for the answer.

I do however have a different problem now when trying to emit an event (rust + sui + move is very new to me). This is the current function:

```rust
    public entry fun place_mark(game: &mut TicTacToe, row: u8, col: u8, ctx: &mut TxContext) {
        
        assert!(row < 3 && col < 3, EInvalidLocation);
        assert!(game.game_status == IN_PROGRESS, EGameEnded);
        let addr = get_cur_turn_address(game);
        assert!(addr == tx_context::sender(ctx), EInvalidTurn);

        let cell = vector::borrow_mut(vector::borrow_mut(&mut game.gameboard, (row as u64)), (col as u64));
        assert!(*cell == MARK_EMPTY, ECellOccupied);

        *cell = game.cur_turn % 2;
        update_winner(game);
        game.cur_turn = game.cur_turn + 1;

        if (game.game_status != IN_PROGRESS) {
            // Notify the server that the game ended so that it can delete the game.
            let id = object::new(ctx);
            event::emit(GameEndEvent { game_id: object::id(game) });
            event::emit(TrophyWonEvent { id: object::uid_to_inner(&id) });
            if (game.game_status == X_WIN) {
                transfer::transfer(Trophy {id}, game.x_address);
            } else if (game.game_status == O_WIN) {
                transfer::transfer( Trophy {id}, game.o_address);
            };
        }
    }

```

However I get an error:

Invalid return

tic-tac-toe.move(107, 17): The local variable ‘id’ might still contain a value. The value does not have the ‘drop’ ability and must be consumed before the function returns

object.move(101, 42): The type ‘(sui=0x2)::object::UID’ does not have the ability ‘drop’

object.move(41, 12): To satisfy the constraint, the ‘drop’ ability would need to be added here

Not sure what’s wrong.

---

<div class="post-metadata">

**Author:** ![amnn](https://dub1.discourse-cdn.com/sui/user_avatar/forums.sui.io/amnn/32/25_2.png) [@amnn](https://forums.sui.io/u/amnn)\
**Post date:** [January 12, 2023, 1:59pm UTC](https://forums.sui.io/t/is-it-possible-to-fetch-by-type/2316/4 "2023-01-12T13:59:03Z")

</div>

The error is saying that you have assigned a value to `id` and the compiler can’t guarantee that it will be used or disposed of correctly before exiting the function.

This is because it doesn’t know that the only valid values for `game.game_status` are `X_WIN`, `O_WIN`, and `IN_PROGRESS`, so it’s thinking that if it’s not any of those, you will have created an `id` and not used it.

To help the compiler out, you can add an `else` case that `abort`s if the `game\_status isn’t as expected:

```rust
const EInvalidGameState: u64 = /* ... */;

struct TrophyEvent has copy, drop {
    trophy_id: ID,
    game: ID,
    winner: address,
}

public entry fun place_mark(game: &mut TicTacToe, row: u8, col: u8, ctx: &mut TxContext) {        
    assert!(row < 3 && col < 3, EInvalidLocation);
    assert!(game.game_status == IN_PROGRESS, EGameEnded);

    let addr = get_cur_turn_address(game);
    assert!(addr == tx_context::sender(ctx), EInvalidTurn);

    let cell = vector::borrow_mut(vector::borrow_mut(&mut game.gameboard, (row as u64)), (col as u64));
    assert!(*cell == MARK_EMPTY, ECellOccupied);

    *cell = game.cur_turn % 2;
    update_winner(game);
    game.cur_turn = game.cur_turn + 1;

    if (game.game_status != IN_PROGRESS) {
        // Notify the server that the game ended so that it can delete the game.
        let trophy = Trophy { id: object::new(ctx) };
        let winner = if (game.game_status == X_WIN) {
            game.x_address
        } else if (game.game_status == O_WIN) {
            game.o_address
        } else {
            abort EInvalidGameState;
        };

        event::emit(GameEndEvent { game_id: object::id(game) });
        event::emit(TrophyWonEvent { 
            trophy_id: object::id(trophy),
            game_id: object::id(game),
            winner,
        });

        transfer::transfer(trophy, winner);
    }
}

```

I also added some extra fields to your `TrophyEvent` to help make sense of it (the game it’s from and the winner in that game), because with just the ID of the trophy, you will struggle to get the full picture (the Trophy may get moved, or wrapped, or deleted after you send it to the address).

---

<div class="post-metadata">

**Author:** ![PauwCrypto](https://dub1.discourse-cdn.com/sui/user_avatar/forums.sui.io/pauwcrypto/32/1188_2.png) [@PauwCrypto](https://forums.sui.io/u/PauwCrypto)\
**Post date:** [January 12, 2023, 5:18pm UTC](https://forums.sui.io/t/is-it-possible-to-fetch-by-type/2316/5 "2023-01-12T17:18:24Z")

</div>

Got it! I did change it up a little bit, since the solution in the answer above still gave some errors.

```rust
    public entry fun place_mark(game: &mut TicTacToe, row: u8, col: u8, ctx: &mut TxContext) {
        assert!(row < 3 && col < 3, EInvalidLocation);
        assert!(game.game_status == IN_PROGRESS, EGameEnded);
        let addr = get_cur_turn_address(game);
        assert!(addr == tx_context::sender(ctx), EInvalidTurn);

        let cell = vector::borrow_mut(vector::borrow_mut(&mut game.gameboard, (row as u64)), (col as u64));
        assert!(*cell == MARK_EMPTY, ECellOccupied);

        *cell = game.cur_turn % 2;
        update_winner(game);
        game.cur_turn = game.cur_turn + 1;

        if (game.game_status != IN_PROGRESS) {
            // Notify the server that the game ended so that it can delete the game.
            event::emit(GameEndEvent { game_id: object::id(game) });
            create_and_send_trophy(game, ctx)
        }
    }

    fun create_and_send_trophy(game: &mut TicTacToe, ctx: &mut TxContext) {
        if(game.game_status != DRAW){
            let trophy = Trophy { id: object::new(ctx) };
            let winner = if(game.game_status == X_WIN) {game.x_address} else {game.o_address};
            event::emit(TrophyEvent { 
                trophy_id: object::uid_to_inner(&trophy.id),
                game: object::id(game),
                winner,
                });
            transfer::transfer(trophy, winner);
        }
    }

```

Emitted event here:

> **[Sui Explorer](https://explorer.sui.io/transaction/12oio4HApoeLjwaok7rUqPKSc2suJqPBbsmB8dsgqSWh)**
>
> Explore transactions, objects, etc. of Sui network
