Decookies is a front-end application, allowing players to bakes cookies on Marigold Sidechain Deku.
-
Git clone this repo
-
Run
npm start
and go tohttp://localhost:3000
to see the minimalist UI:
-
Filfill the
Deku node URI
with the URI of your running Deku node -
Login using
Beacon wallet
.
**
⚠️ The only thing Decookies will ask you to sign, is the "delegation". Under the hood, we generate a random private key to sign all the operations submitted to Deku.⚠️ **
The delegation operation submitted to Deku is:
Delegate({onBehalfOf: \"tz1xxx\" as address})
Where tz1xxx
is your Beacon public address. This operation will be submitted to Deku via the randomly generated key, and will allow decookies to bake cookies from the generated address, and link them to your real Beacon address.
Here is an example of the state on Deku side:
"state":
[ "Map",
[ [ [ "String", "tz1xxxxx" ],
[ "Pair",
[ [ "Pair",
[ [ "Pair",
[ [ "Pair",
[ [ "Pair",
[ [ "Set",
[ [ "String",
"tz1Generated1" ],
[ "String",
"tz1Generated2" ],
[ "String",
"tz1Generated3" ],
[ "String",
"tz1Generated4" ],
[ "String",
"tz1Generated5" ] ] ],
[ "Int", "60" ] ] ],
[ "Pair",
[ [ "Int", "0" ], [ "Int", "2232516" ] ] ] ] ],
[ "Pair",
[ [ "Pair", [ [ "Int", "57" ], [ "Int", "1" ] ] ],
[ "Pair",
[ [ "Int", "1220491" ], [ "Int", "0" ] ] ] ] ] ] ],
[ "Pair",
[ [ "Pair",
[ [ "Pair",
[ [ "Int", "50" ], [ "Int", "172" ] ] ],
[ "Pair",
[ [ "Int", "1" ], [ "Int", "115" ] ] ] ] ],
[ "Pair",
[ [ "Pair", [ [ "Int", "1" ], [ "Int", "40" ] ] ],
[ "Pair",
[ [ "Int", "0" ], [ "Int", "15612" ] ] ] ] ] ] ] ] ],
[ "Pair", [ [ "Int", "2314" ], [ "Int", "2" ] ] ] ] ] ] ] ]
In this case, tz1xxxxx
is my actual Beacon public address, and tz1GeneratedX
are every generated keys allowed to bake cookies for me. A new random key is generated each time you disconnect your wallet.
- Bake cookies!
We basically implemented the same scenario as cookie-clicker.
Hence, the levels are almost the same (still in WIP) and the costs calculation is almost the same.
The goal of this game is to bake as many cookies as possible. To do so, there are several ways:
- Click on the cookie button. Each click will submit one cookie to be baked to Deku (cookie in oven). Once the operation had been included in a block, you will have the cookie.
- Buy buildings to passively bake cookies for you. For example, you can buy your first Cursor for 15 cookies. Once the cursor had been baked, it will bake one cookie per second for you.
We added a feature to transfer cookies from your game to an other player. You simply need to fulfill the amount and the recipient address.
What is a cookie baking game if we cannot eat them?
Hence, we added this feature. Let's see who is the biggest eater! A leaderboard will be available to see who has eaten the more cookies! Let's eat yours!
- Who are Marigold? And what are they working on?
Marigold is a dynamic and collaborative company, established by Gabriel Alfour in November 2020, focused on testing and developing upgrades to the Tezos Protocol.
We have several projects, and one of them is the Deku sidechain.
Decookies, is a game running on this Deku sidechain.
- What is the cookie-clicker game?
At the genesis of this project, we had two different goals:
- Create a blockchain app to betatest our onboarding on Deku-P
- Test Deku transaction per second
We decided to develop a gam to do them both! We chose to do a cookie-clicker game like (we were mainly inspired by this one from Orteil), because it will force us to:
- reach high TPS on Deku side
- develop blockchain app
- develop front to interact with blockchain app
A first article had been posted on Marigold blog to create your first Blockchain App. Decookies, is a front allowing players to interact with the related Blockchain App, running on Deku Parametric AKA Deku-P.
- Decookies asks me to sign an operation, what is it?
To preserve the gameplay, we need to use the InMemorySigner
from Taquito. This signer needs the Private key and Public address of the user. Of course, we are not going to ask for your private key (because you know you must never share it).
Hence, we use the Beacon SDK to sign a payload submitted to Deku. This payload is simply:
Delegate({onBehalfOf: \"tz1xxx\" as address})
Which means, the randomly generated private key, will be able to bake cookies for you, on Deku side.
Please note, this is the only payload you will ever have to sign from Decookies. Of course, if you change browser or whatever, you will have to sign, again, this same payload, but for an other random private key.
On Deku side, your state will look like:
"state":
[ "Map",
[ [ [ "String", "tz1xxxxx" ],
[ "Pair",
[ [ "Pair",
[ [ "Pair",
[ [ "Pair",
[ [ "Pair",
[ [ "Set",
[ [ "String",
"tz1Generated1" ],
[ "String",
"tz1Generated2" ],
[ "String",
"tz1Generated3" ],
[ "String",
"tz1Generated4" ],
[ "String",
"tz1Generated5" ] ] ],
[ "Int", "60" ] ] ],
[ "Pair",
[ [ "Int", "0" ], [ "Int", "2232516" ] ] ] ] ],
[ "Pair",
[ [ "Pair", [ [ "Int", "57" ], [ "Int", "1" ] ] ],
[ "Pair",
[ [ "Int", "1220491" ], [ "Int", "0" ] ] ] ] ] ] ],
[ "Pair",
[ [ "Pair",
[ [ "Pair",
[ [ "Int", "50" ], [ "Int", "172" ] ] ],
[ "Pair",
[ [ "Int", "1" ], [ "Int", "115" ] ] ] ] ],
[ "Pair",
[ [ "Pair", [ [ "Int", "1" ], [ "Int", "40" ] ] ],
[ "Pair",
[ [ "Int", "0" ], [ "Int", "15612" ] ] ] ] ] ] ] ] ],
[ "Pair", [ [ "Int", "2314" ], [ "Int", "2" ] ] ] ] ] ] ] ]
and you can verify this by running:
$ curl https://deku-canonical-vm0.deku-v1.marigold.dev/api/v1/state/unix/DK1DpUMB44Ex3WXEUXPjp9DDkjiQ5cyvVwoU/
This will print the entire state of Decookies contract deployed on Deku.
- How can I know the public address of my game, to ask cookies from a friend?
As explained previously, the Public Address is generated. It is now displayed right below the form you have to complete.
stateDiagram-v2
direction LR
Player --> cookieBaker
cookieBaker --> Cursors
cookieBaker --> Grandmas
cookieBaker --> MintCookie : Click to mint one cookie
MintCookie --> cookieBaker : Receive one cookie
state BuyCursor <<BuyCursor>>
cookieBaker --> BuyCursor
BuyCursor --> NotEnoughCookie: if cookieBaker.cookies < cursorCost
BuyCursor --> +1Cursor : if cookieBaker.cookies >= cursorCost
BuyCursor --> cookieBaker: add one cursor
state BuyGrandma <<BuyGrandma>>
cookieBaker --> BuyGrandma
BuyGrandma --> NotEnoughCookie: if cookieBaker.cookies < grandmaCost
BuyGrandma --> +1Grandma : if cookieBaker.cookies >= grandmaCost
BuyGrandma --> cookieBaker: add one Grandma
Cursors --> MintCookie : Each cursor mint 1cps
MintCookie --> cookieBaker : Receive 1cps
Grandmas --> MintCookie : Each grandma mint 3cps
MintCookie --> cookieBaker : Receive 3cps
CPS=Cookies Per Second
TL;DR;
Each player as a cookieBaker
type, which stores every counters:
- number of cookies
- number of cursors
- number of grandmas There are several possible actions:
- mint a cookie => simply add one cookie in the current amount of cookies
- buy a cursor => if enough cookie to buy one, add one cursor to the current amount of cursors. Every seconds, one cursor will mint one cookie for the user.
- buy a grandma => if enough cookies to buy one, add one grandma to the current amount of grandams. Every secondes, one grandma will mint three cookies for the user.
sequenceDiagram
participant Player2
actor Player1
participant State
participant Cursor
Note right of Cursor: Cursor initial cost is 15 cookies
participant Grandma
Note right of Grandma: Grandma initial cost is 100 cookies
loop Each click
Player->State: Mint 1 cookie
end
loop Each second
loop Each cursor
Cursor->State: Mint 1 cookie
end
end
loop Each second
loop Each grandma
Grandma->State: Mint 3 cookies
end
end
critical Buy a Cursor
Player-->State: buy cursor
option Enough cookies
State-->State: Player has one more cursor
end
critical Buy a Grandma
Player-->State: buy Grandma
option Enough cookies
State-->State: Player has one more Grandma
end
critical Send cookies
Player1-->Player2: send 3 cookies
option Enough cookies
State-->State: Player1 has enough cookies
end