Micro Cow combines Rust-based smart contracts built with Linera, and a web app client to access the smart contracts functionality built with one of the most popular cross-platform frameworks, Flutter.
Micro Cow smart contract will cover several capabilities of Linera that exist in the Devnet, which include:
- Authentication
- Cross-Chain Messages
- Custom Types
- Contract Instantiation
- Instantiation Argument
- Application Parameters
- Channel Subscription
While the Micro Cow web app will cover the following:
- Setting Linera wallet through calls to node service
- Calling Linera smart contract function using GraphQL
This article is specifically about the Linera smart contract for Micro Cow.
Discussion of the Micro Cow web app is in the Micro Cow App repository
The Micro Cow smart contract in this repository was developed using Rust version 1.77.2
, linera-service v0.11.3
,
and linera-sdk v0.11.3
The first step you have to do is install Rust. You can follow the steps to install Rust in the following article:
- Install Rust - Rust Programming Language
- Walkthrough: Installing Rust on Windows
- How To Install Rust on Ubuntu 20.04
Next we install Linera SDK and Linera Service:
cargo install --locked [email protected]
cargo install --locked [email protected]
Confirm that both Rust and Linera CLI are installed by running rustc --version
and linera --version
.
You should receive a result that is more or less similar to:
rustc 1.77.2 (25ef9e3d8 2024-04-09)
Linera protocol: v0.11.3
RPC API hash: package not used
GraphQL API hash: package not used
WIT API hash: package not used
Source code: https://github.com/linera-io/linera-protocol/tree/v0.11.3
You should be aware that currently we can't install Linera Service on Windows.
Please refer to the following installation document from Linera dev team: Linera Installation
Before we build and deploy the contract, we have to prepare a ChainID to be used as Root ChainID for the Micro Cow contract.
In this example, we will use ChainID b12f5885bb54ea25d26cbb59795e249392b0c8892df11e51c31aea77befbabbb
as the
Root ChainID in the --json-parameters
, and we will set the --jason-argument
with 500000
LINERA token as
starting balance for the Root ChainID.
-
Clone the repository:
git clone https://github.com/hasToDev/micro_cow_linera.git
-
Build and Deploy the contract:
linera project publish-and-create \ --json-argument '"500000"' \ --json-parameters "{ \"root_chain_id\": \"b12f5885bb54ea25d26cbb59795e249392b0c8892df11e51c31aea77befbabbb\" }"
After the deployment is complete, you will receive an Application ID.
Save the Application ID because you will need it when playing the game with Micro Cow app.The form of Application ID will be similar to
b12f5885bb54ea25d26cbb59795e249392b0c8892df11e51c31aea77befbabbb000000000000000000000000b12f5885bb54ea25d26cbb59795e249392b0c8892df11e51c31aea77befbabbb020000000000000000000000
To play the Micro Cow game, you will need:
- a ChainID that is different than the Root ChainID
- running
linera service
on your device or local network - Micro Cow Application ID that was deployed on Root ChainID on your device or local network
Lets say in your linera wallet
, there are 4 ChainID:
b12f5885bb54ea25d26cbb59795e249392b0c8892df11e51c31aea77befbabbb
f0e5dc9ee7e43fd15892ecce4638b4a2d1a1770423152928f895b3b5c2cbb2ba
3dead76577bb77e16b30deca479efc222f7273cb07d0bc1fc30dc09a402ece4e
9b66c79b48abec64fa05d6610ff14c84ab667790febb9e2a0abc890b162d7931
You have use b12f5885bb54ea25d26cbb59795e249392b0c8892df11e51c31aea77befbabbb
as a Root ChainID when you deploy
the Micro Cow contract.
Therefore, you can use the remaining ChainID to play the game.
On the first time you play Micro Cow, the app will check if Micro Cow exist in your chain. It will make a request to the root chain if Micro Cow doesn't exist.
After request complete, the contract will then call CowOperation::Initialize to initialize a new game account in your chain. Your account will start with 10000 LINERA token.
The contract will also send a channel subscription request to the root chain, so that your chain will stay updated with all things that happens on root chain.
When we buy a cow in the game, the app will call CowOperation::BuyCow on the player chain.
It will then:
- check if the Cow Name that you want is available
- check if you have enough balance to buy the cow
- debit your balance to pay for the cow
- send Message::BuyCow to the root chain
on the root chain, after receiving the Message::BuyCow, it will:
- check if the Cow Name that you want is available
- send Message::BuyFailure back to you because the Cow name is already registered
- register the new cow
- credit balance to receive payment
- send Message::BuySuccess to the channel subscriber if the process succeed
back on the player chain, there are 2 possible message that you will receive at the end of this function call, * Message:: BuyFailure* and Message::BuySuccess
For the Message::BuyFailure, it will:
- credit the balance back to your account because you fail to buy the cow, and notify player that the buy is a failure
- save the Cow data that was sent by root chain, this data is existed on root chain state, but not in yours
For the Message::BuySuccess, it will:
- save the new Cow data in all channel subscriber
- add the new Cow name to buyer's ownership list, and notify player that the buy is a success
- remove the Cow name from other player's ownership list
When we feed a cow in the game, the app will call CowOperation::FeedCow on the player chain.
It will then:
- make sure that the cow is in your ownership, you aren't allowed to feed another player's cow
- find out if the cow is hungry or still full
- update the cow data with the next feeding time
- send Message::FeedCow to the root chain
on the root chain, after receiving the Message::FeedCow, it will:
- save your cow latest data to it's state
- send Message::FeedSuccess to the channel subscriber
back on the subscriber chain, after receiving the Message::FeedSuccess, it will save your cow latest data on subscriber's state. That way, all subscriber knows that your cow has been fed.
When we sell a cow in the game, the app will call CowOperation::SellCow on the player chain.
It will then:
- make sure that the cow is in your ownership, and still alive
- find out if the cow is underage, you can't sell any cow that have age less than 3 days
- send Message::SellCow to the root chain
- on the web app side, the game will ask for your confirmation of Cow selling price. If you agree with the price, then and only then the game will call CowOperation::SellCow on the contract side
on the root chain, after receiving the Message::SellCow, it will:
- calculate how much the cow is worth, based on its feeding stats
- check if root chain have enough balance to pay for the cow
- if the balance not enough, it will send Message::SellFailure back to you to notify that root chain can't buy your cow, at least at the moment of invocation
- remove your cow from root chain state
- debit root chain balance to pay for the cow
- send Message::SellSuccess to the channel subscriber
back on the player chain, there are 2 possible message that you will receive at the end of this function call, Message::SellFailure and Message::SellSuccess
For the Message::SellFailure, it will only notify the seller that the sell process can't continue for now.
For the Message::SellSuccess, it will:
- remove the Cow name from seller ownership
- credit the seller balance to receive payment for the cow
- notify the seller that the sell process is successful
- remove the Cow data from all subscriber's state
The web app side of Micro Cow game will utilize the unmetered query service on Micro Cow smart contract to get any required data, to make sure that every operation calls is successful.
Some of the GraphQL query that available in this contracts are:
root_check
: check if this chain is a root chainstatus_check
: check the initialization status of this chainget_owner
: get the owner of this chainget_balance
: get balance Micro Cow balance for this chainget_one_buy_notification
: get 1 buy notification if it existedget_one_sell_notification
: get 1 sell notification if it existedget_my_cows
: get all the cows owned by this chainis_cow_alive
: check if a cow with certain name is still aliveget_cow_existence
: check if a cow is existed in local DB, and owned by this chainis_cow_underage
: check if a cow's age in less than 3 daysget_cow_sell_value
: get a cow appraisal price based on its name & statsis_cow_still_full
: check if cow still full based on its last feeding time
The Micro Cow is distributed under an MIT license. See the LICENSE for more information.