In the previous parts of this tutorial series we have guided you on how to create a new Calimero shard and how to deploy the tic tac toe game as a smart contract on Calimero, here are the links to part 1 and to part 2. In the third part of the tutorial we are going to dig a bit deeper into how to make cross shard contract calls between NEAR and Calimero network (which are separate chains).
Running a complex turn-based game completely on NEAR would be expensive, as each move would be a new transaction for which gas would need to be paid. For simplicity of demonstration we have implemented a tic tac toe game. Here is how we can leverage cross shard contract calls to cut gas costs:
Also, note, for simplicity we implemented tic tac toe, but the difference would be even greater if playing a more complex game on chain with far more needed moves (transactions), such as chess, for which gas savings would be even bigger.
Here is the source code of the contract that matches two players, and initiates a new game on Calimero
To make cross shard contract calls easier to use and to reduce boilerplate code for developers making such calls, we have published the Calimero Rust SDK on the Rust community’s crate registry. Let's examine the matchmaking contract.
Apart from standard imports of near_sdk that are needed for deploying a contract on NEAR, on line 10 we also import the calimero_sdk:
We will go through each imported item. Firstly, the calimero_cross_shard_connector which is used on line 53:
This macro needs to be defined before making a cross_call, or receiving a cross_call_receive_response which are internal cross shard connector calls wrapped by the SDK so that the developer does not need to know the internals, but if such knowledge is wanted, it can be obtained as all the cross shard connector code is open sourced or read more details in the docs
In the given contract it is defined that the matchmaking will interact with xsc_connector.demos.calimero.testnet. The calimero_cross_shard_connector is a proc_macro that actually translates into generated code, it simply sets a const that will be needed for later use.
On line 79, the register_player method is defined, here it is as well:
What this logic does is, if there is no one waiting to start a game, assign the current method caller (env::predecessor_account_id()) as the waiting player. Otherwise, the current method caller can be matched with previous caller and the calimero_cross_call_execute macro will be called.
This macro creates and returns the promise that will make the cross_call. We pass all the needed information to this macro - for execution on the other chain (in this case, to start the game on Calimero side):
It needs to be used before #[near_bindgen] as we want to expand the #[calimero_receive_response] before near_bindgen as calimero_receive_response modifies function signature, and near bindgen generates code related to input params. Here is how to use it:
And the actual callback method:
The method above will be called once the game starts on Calimero. For curious readers, the method actually expands to:
If the method above executes without panicking, it means the game has started on Calimero, and now the contract on NEAR side has noted it.
This contract was already deployed in the previous blog post, but here is once more the source codeof the contract.
On line 50, we define the corresponding cross shard call connector for Calimero side:
On line 70, the start_game method is defined that will be called by the cross shard connector once a game is initiated from NEAR side.
Between lines 86 and 174, the game logic is defined, among others, the conditions of ending the game, upon which a cross call is being initiated to note this back to NEAR side:
Also, the defined params:
Once the cross_call, that will execute game_ended on NEAR side executes, the contract on NEAR side has the info about who has won. Optionally we provided the callback_game_ended method on Calimero contract that just logs that the game_ended method was called on NEAR side.
We have examined logic for making cross shard calls from NEAR to Calimero and from Calimero to NEAR by using the Calimero Rust SDK which is published here. We are excited to see what cross shard contract calls the community will come up with their use cases. Also, stay tuned for the next part of the tutorial series, where we will show the full flow with NEAR testnet and Calimero transactions for playing the game.