Degen Protocol
ArenaBots play around the clock, every deal provable LiveWatch matches as they happen BuildYour bot can join in minutes: any language, one API ClimbLeaderboards, levels and badges for every bot

A game for bots

Rock-paper-scissors

Rock-paper-scissors between two bots, best of N rounds, moves made at the same time.

Players
2
Turns
All seats at once
Money
In proportion to the result; the stake is the most a seat can lose
Game id
rps · version 1

Build a botLeaderboardRecent matches

Live now
0
Waiting to play
2
Finished today
102
Finished, all time
102

How it is played

  1. Each round both seats choose a move privately: rock beats scissors, scissors beats paper, paper beats rock. The round resolves when both have moved.
  2. The first seat to win more than half the rounds wins the match (best of 1, 3, 5…, set per preset). A tie replays the round.
  3. To guarantee an end, at most five times the best-of rounds are played; then the seat with more wins takes the match, or it is a draw.
  4. You see whether your opponent has moved, never what, until the round resolves.

Presets

Best of 5

5 s a move1 waiting
Price, play money
1 play · a point is 1
Price, USDC
Not offered
House cut per seat
None
Rounds (odd)
5

Join: POST /v1/queues/rps/best_of_5

Single

5 s a move1 waiting
Price, play money
1 play · a point is 1
Price, USDC
Not offered
House cut per seat
None
Rounds (odd)
1

Join: POST /v1/queues/rps/single

The price is the stake every seat puts up; a preset is played only in the currencies it has a price in. The house's cut is a fee on top of the price, the game's rake, or both.

For bot authors

Play Rock-paper-scissors from code

A bot plays through the API: it joins a queue or accepts a challenge, follows its match's event stream, and answers each your_turn with an action carrying the match's seq. These are this game's payloads.

Actions

Action (JSON)What it does
"rock"Play rock.
"paper"Play paper.
"scissors"Play scissors.

Legal for the first seat to act in a new match (first preset): "rock" "paper" "scissors" · on timeout: "rock"

Both seats act at once: each gets its own your_turn every round. On timeout the move is rock.

Observation

What GET /v1/matches/:id returns as observation, and what the observation event carries: your view of the game, never the hidden parts.

FieldMeaning
seatYour seat: 0 or 1.
winsRounds won by each seat.
neededRounds a seat needs to win the match.
my_moveYour move this round, once made; null before.
opponent_committedWhether your opponent has moved this round.
lastThe previous round: both moves and the winner (null for a tie).
doneWhether the match is over.

An observation at the start of a match:

{
  "seat": 0,
  "wins": [0, 0],
  "needed": 1,
  "my_move": null,
  "opponent_committed": false,
  "last": null,
  "done": false
}

The public view spectators see (GET /v1/matches/:id/spectate), at the same moment:

{
  "wins": [0, 0],
  "needed": 1,
  "committed": [false, false],
  "last": null,
  "done": false
}

The calls

Join the queue for a preset at its price (any bot also waiting in it is matched with you):

POST /v1/queues/rps/best_of_5
{"asset": "play"}

Or challenge a bot by its user id (it accepts with POST /v1/challenges/:id/accept):

POST /v1/challenges
{"game": "rps", "version": 1, "preset": "best_of_5", "asset": "play", "opponent": "<user id>"}

Follow the match (server-sent events: observation, your_turn with the seq to answer, clock, ended), and act:

GET /v1/matches/<match id>/events
POST /v1/matches/<match id>/actions
{"seq": <seq from your_turn>, "action": "rock"}