# Play With Cross-Chain Tokens
Make sure you have all you need before proceeding:
- You understand the concepts of messages, Protobuf, and IBC.
- Go is installed.
- You have the checkers blockchain codebase up to the can play query. If not, follow some previous steps or check out the relevant version (opens new window).
In this section, you will:
- Discover the Inter-Blockchain Communication Protocol.
- Accept wagers with tokens from other chains.
- Refactor integration tests.
When you introduced a wager you enabled players to play a game and bet on the outcome using the base staking token of your blockchain. What if your players want to play with other currencies? Your blockchain can represent a token from any other connected blockchain by using the Inter-Blockchain Communication Protocol (IBC).
Thus, you could expand the pool of your potential players by extending the pool of possible wager denominations via the use of IBC. How can you do this?
Your checkers application will be agnostic regarding tokens and relayers. Your only task is to enable the use of foreign tokens.
# Some initial thoughts
Before diving into the exercise, ask yourself:
- What new information do you need?
- How do you sanitize the inputs?
- Are there new errors to report back?
- What event should you emit?
# Code needs
When it comes to the code itself:
- What Ignite CLI commands, if any, assist you?
- How do you adjust what Ignite CLI created for you?
- How would you unit-test these new elements?
- How would you use Ignite CLI to locally run a one-node blockchain and interact with it via the CLI to see what you get?
# New information
Instead of defaulting to "stake"
, let players decide what string represents their token:
Update the stored game:
Update the message to create a game:
Instruct the Ignite CLI and Protobuf to recompile both files:
It is recommended to also update the
MsgCreateGame
constructor:Not to forget the CLI client:
This new field will be emitted during game creation, so add a new event key as a constant:
# Additional handling
The token denomination has been integrated into the relevant data structures. Now the proper denomination values need to be inserted in the right instances at the right locations:
In the helper function to create the
Coin
infull_game.go
:In the handler that instantiates a game:
Also where it emits an event:
# Unit tests
The point of the tests is to make sure that the token denomination is correctly used. So you ought to add a denomination when creating a game (opens new window) and add it to all the stored games (opens new window) you check and all the emitted events (opens new window) you check. Choose a "stake"
for all first games and something else for additional games, for instance "coin"
(opens new window) and "gold"
(opens new window) respectively.
Adjust your test helpers too:
The coins factory now needs to care about the denomination too:
To minimize the amount of work to redo, add an
ExpectPayWithDenom
helper, and have the earlierExpectPay
use it with the"stake"
denomination:Do the same with
ExpectRefund
(opens new window).
With the new helpers in, you can pepper call expectations with "coin"
(opens new window) or "gold"
.
# Integration tests
You have fixed your unit tests. You need to do the same for your integration tests.
# Adjustments
Take this opportunity to expand the genesis state so that it includes a different coin.
Make sure your helper to make a balance cares about the denomination:
Since you want to add more coins, make a specific function to sum balances per denomination:
In the bank genesis creation, add new balances:
Also adjust the helper that checks bank balances. Add a function to reduce the amount of refactoring:
# Additional test
With the helpers in place, you can add a test with three players playing two games with different tokens:
All your tests should now pass.
# Interact via the CLI
Restart Ignite with chain serve
. If you recall, Alice's and Bob's balances have two token denominations. Query:
This returns what you would expect from the config.yml
(opens new window):
You can make use of this other token
to create a new game that costs 1 token
:
Which mentions:
Have Alice play once:
Which mentions:
This seems to indicate that Alice has been charged the wager. As a side node, cosmos16xx0e457hm8mywdhxtmrar9t09z0mqt9x7srm3
is the checkers module's address. Confirm it:
This returns:
Correct. You made it possible to wager any token. That includes IBC tokens.
Now check the checkers module's balance:
This prints:
That is correct.
# Live testing with a relayer
With the checkers application ready to accommodate IBC-foreign tokens, you should run some tests locally with another blockchain's tokens without running a large-scale operation. Conveniently, Ignite CLI has the TypeScript relayer (opens new window) built in. If you look at the GUI Ignite CLI created in your checkers blockchain, you will see a Relayers section on the left.
A relayer is a process that transfers IBC packets between two blockchains. Here this process is running in your browser using the account you configured in your browser. The account is the same one you would use to play a game of checkers. Dub it alice123@checkers
.
- On the checkers end, the relayer is already configured to connect to your running checkers blockchain and to use the tokens of whichever account you have configured in your browser (here
alice123@checkers
). Therefore, it gets the same privileges to access your tokens that you have granted to the checkers browser application. - You need to configure it to connect to the other blockchain which hosts the foreign tokens you want to transfer. This can be the Cosmos Hub, or a testnet (opens new window) that you or someone else runs.
- You also need to fund the relayer's account on the remote chain so that it can operate. The account is generated from the same private key as
alice123@checkers
, so call italice465@remote
. The relayer shows you in the browser which account this is.
Your test follows a few steps:
- Configure the relayer. This is a matter of entering the necessary parameters, clicking a button, and waiting for the setup to be done. In effect, the relayer opens a transfer channel (likely numbered
0
) on the checkers chain, opens another transfer channel on the remote chain, and links the two. - Send the desired foreign tokens to
alice465@remote
using any regular method of sending tokens, independent of whether the tokens come from a faucet or another account. - Use the relayer to send these foreign tokens to
alice123@checkers
. - Check the balance of
alice123@checkers
in the checkers blockchain when it is done. You should see a new entry whosedenom
field looks like a long hex value (ibc/1873CA...
). Save this string to use with your test. - Repeat the transfer process through the relayer, this time for the benefit of another player (for example
bob224@checkers
). For your test, Alice can send some tokens to Bob so they can start a game. - Have Alice and Bob start a game with
token: ibc/1873CA...
. - After the outcome of a game, the players can retransfer these foreign tokens via the same relayer to the remote chain.
This is how the TypeScript relayer built in by Ignite CLI lets you experiment with foreign tokens.
As soon as you close the browser window the channels on both ends are no longer monitored, and therefore no token transfers will take place. Also depending on the development state of Ignite CLI, after you close it the relayer may not be able to reuse a channel it created earlier. Do not use this for production.
To summarize, this section has explored:
- How to enable the use of cross-chain tokens to make wagers on checkers games as well as your blockchain's base staking token, by making use of the Inter-Blockchain Communication Protocol (IBC).
- How to update the stored game and the game creation message to allow players to decide what string represents their token.
- Where to insert the necessary values to allow recognition of token denominations.
- How to fix your existing tests due to the introduction of a new field and a new event, and how to add a new test when a player makes their first move.
- How to interact via the CLI to confirm the presence of the new token denomination in a player's balance and that using these tokens to make a wager functions as required.
- How to demonstrate that your application will accept IBC-foreign tokens from another blockchain, using Ignite CLI's built-in TypeScript relayer as a convenient small-scale local testing tool.
Alternatively, you can learn how to create the TypeScript client elements for your blockchain.