Errors, events and views
Errors
Return an ActionError to fail a transaction:
| Constructor | Use it when |
|---|---|
ActionError::invalid(msg) | the op is malformed or illegal right now (cell taken, bad stake) |
ActionError::unauthorized(msg) | the sender may not do this (not your turn, not a player) |
ActionError::not_found(msg) | the thing the op names does not exist (unknown game id) |
There are also Insufficient (raised by the chain when a balance is too low), Conflict and Internal. The
error text goes into the receipt, so write messages a player can act on: "cell is taken", not "bad".
The transaction is still in the block with ok: false; its state changes are gone and its nonce is spent.
Events
Emit an event for every change a UI cares about, with a namespaced kind:
tictactoe.created{id, x, stake, opponent}tictactoe.joined{id, o}tictactoe.moved{id, by, cell, board, turn}tictactoe.finished{id, result, winner, reason, payout}
Document them at the top of the file, as tic-tac-toe does, because the browser game is written against them.
Views
view receives the read-only state and the query string as a map. Tic-tac-toe supports:
?id=<id>: one game,?open=1: open games anyone may join (at most 50),?player=<address>: that player's games,- no parameters: a small description of the module (
timeout_blocks,max_stake).
Lists scan open/ or player/<address>/ keys with state.scan_raw, always with a limit, and sort by
created_height so the order never depends on storage.