CryptoBotWars or How to Build Shitty Demos and Why

Why shitty ? Because I like self deprecation and the game is no where near production.

Tokens, Robots, Payment Channels and Live Streams

So I built CryptoBotWars, a game on Raiden Network.

Behind the scenes

Why? … I had some questions:

  1. Is it easy to build something on top of Raiden right now? Do we lack anything that is fairly easy to change?
  2. How would Raiden work right now for one-to-many & many-to-one payments, cases frequently related to businesses
  3. Would people find bugs in Raiden? The best testers are the clueless, newly onboarded testers.
  4. Would Raiden behave nicely with high throughput?
  5. Would payments be successfully mediated (various locations & system setups)
Dark Vader and Blue Yoda. Soup bowl & ping-pong Santa Hat! Looks great! … from 4m away 😛

How did the idea come about?

One day, over lunch, we were discussing ideas for the Devcon4 Raiden Network workshop, trying to think of a fun and simple app that can be built on top of Raiden. Somehow, we got to the conclusion that a game may incentivize more people to try it out.

Robots Want Crypto

You have a game, you have Raiden, why add another variable to the equation?

  1. Robots are fun and cute (🤖 vs. 😼 meme duel now!)
  2. I put my Yoda voice to work! (the beginning of yet another career..)
  3. But actually robots give us a sense of what the future could be 🚀.

How did I start building?

~5.5 days were enough to do the initial setup & robot prototype connections for ETHSingapore.

  1. GameGuardianServer
  2. GameGuardianRaidenNode
  3. GameClient
  4. Live Stream on Twitch
export const GameState = {
null: 0, // No current game running
open: 1, // During game time, users can make moves closed: 2, // During game resolution time, users wait for results and payments resolved: 3, // Game and resolution has ended.}
moves = await moveController.find({where: {gameId: id}, order: ["_id ASC"]});raidenPayments = await this.getRaidenPayments(TOKEN)moves.forEach(sentMove => {
if (
sentMove.amount &&
sentMove.move &&
sentMove.amount >= game.move_amount
) {
raidenPayment = raidenPayments[0].find((payment) => {
return payment.identifier === sentMove.paymentIdentifier;
if (raidenPayment) {
total_amount += sentMove.amount;
move_count[sentMove.playerId][sentMove.move] += 1;

sorted_moves_1 = Object.entries(move_count['1']).sort((a: any, b: any) => {return a[1] - b[1]});
sorted_moves_2 = Object.entries(move_count['2']).sort((a: any, b: any) => {return a[1] - b[1]});
move1 = sorted_moves_1[2][1] > 0 ? sorted_moves_1[2][0] : null;
move2 = sorted_moves_2[2][1] > 0 ? sorted_moves_2[2][0] : RockPaperScissorsGetLoser[move1];
// If we have one player, make sure he wins
if (!move1) {
move1 = RockPaperScissorsGetLoser[move2];
winningMove = RockPaperScissorsGetLoser[move1] === move2 ? move1 : move2;
validMoves.forEach((move) => {
// We reward both players if their final moves are the same
if (move.move === winningMove) {
guardian_amount = total_amount / 10;
total_amount -= guardian_amount;
winner_amount = total_amount / winningMoves.length;
gameUpdate = {
player1: <PlayerResult> {
count: sorted_moves_1[0][1] + sorted_moves_1[1][1] + sorted_moves_1[2][1],
move: move1,
move_count: move_count['1'],
player2: <PlayerResult> {
count: sorted_moves_2[0][1] + sorted_moves_2[1][1] + sorted_moves_2[2][1],
move: move2,
move_count: move_count['2'],
amount: winner_amount,
amountGuardian: guardian_amount,
players: moves.length,

this.updateById(id, gameUpdate);
// Make Raiden payments to winners
winningMoves.forEach((move) => {
this.sendRobotCommands(move1, move2, winningMove);


Sparked your interest? Try out the game:

Building bricks for the World Computer #ethereum #Pipeline #dType #EIP1900,