IBC Cross-Chain Transfers Technical Tutorial
Welcome to the Coreum workshop on Inter-Blockchain Communication (IBC) transfers, a revolutionary technology enabling secure and reliable data and value exchange between different blockchain networks. IBC is a protocol that allows independent, sovereign blockchains to communicate and transact with each other, thus creating an interconnected ecosystem of blockchains.
What You Will Learn
During this workshop, the Coreum engineering team will dive deep into the mechanics of IBC transfers, exploring how they work under the hood.
- Frontend Integration with Next.js and Keplr Wallet
- The Coreum team will begin with a detailed tutorial on setting up a dynamic and responsive UI using Next.js, a popular React framework known for its efficiency and versatility.
- You’ll learn how to integrate the Keplr Wallet into this environment, enabling users to securely manage their blockchain assets and initiate IBC token transfers directly from the interface.
- Setting up Next.js for blockchain applications. Incorporating Keplr Wallet for authentication and transaction signing.
- Designing a user-friendly interface for token transfers and asset management.
- Backend Integration with Cosmos.js and Coreum.js: Moving to the backend, developers will dive into using Cosmos.js and Coreum.js for handling the complex logic of blockchain transactions and IBC transfers. This segment will detail how to set up and interact with blockchain networks, create and broadcast transactions, and ensure the security and reliability of cross-chain operations.
Live workshop:
https://www.youtube.com/watch?v=o4rrvBb5dbU
Additional Resources: Coreum Blockchain Workshops: Master dApp Development
Welcome to the Coreum App Workshop!
In this hands-on workshop, you’ll dive into the world of decentralised app (DApp) development using the Coreum App Boilerplate. This tutorial is designed to equip you with the knowledge and tools necessary to deploy a Coreum DApp, integrating key technologies and best practices.
🚀Prerequisites
- Basic knowledge of TypeScript and React.
- One of the following wallets installed: Keplr, Leap, Cosmostation, or Frontier.
🏦 Make Sure To Also Connect Your Keplr Wallet To Coreum
To interact with the Coreum blockchain, connecting your Keplr wallet is essential. Here’s a step-by-step guide:
Install Keplr Wallet here Download Keplr Wallet | Official Website
1. Open Keplr Wallet: Launch your Keplr wallet extension in your browser.
2. Manage Chain Visibility: Click on the burger menu and select “Manage Chain Visibility”.
3. Add Coreum Network: Search for “Coreum” and enable it in the network list.
4. Save Your Selection: After selecting “Coreum”, click the “Save” button.
You should now see Coreum in your Keplr wallet’s list of chains, ready to interact with the Coreum blockchain.
🛠 Getting Started
For this workshop we are going to review the code and different components of a simple application where you can facilitate cross chain transfers with IBC. Lets first copy the code and run the application from a computer. Visit this repo Jahanzeb9999/workshops at new-branch (github.com)
Download the folder into a new folder called IBC-Transfer-Dapp. You will need to have visual studio code or a similar application installed to view the code on your local machine.
Installation
open a terminal (Command Prompt on Windows, Terminal on macOS and Linux). Then CD to the file directory where you want to clone the repository.
Now make sure Node.js is installed as this next step involves working with the node package manager. You can install it by visiting their website. Next cd into the folder where the repo is stored and then cd into the repo. Run this command.
Now finally you can run the application by running this command
You should now be able to search for localhost:3000 in your browser and see a web page that looks like this.
Now to sign with your new wallet hit the connect wallet button and you should see a panel like this:
🎉 Congratulations!
You’ve now successfully set up the Coreum IBC Transfer Repo and your Keplr. Happy coding! We will walk through this app and the various files and go through what each one means.
Now Let’s Dive Into The Workshop: **Happy DApp Building!** 🚀
Let’s take a look at the architecture of IBC before diving into our main repo
IBC is designed to enable secure and reliable communication between different blockchain networks, allowing them to transfer tokens and other data among each other while maintaining their autonomy.
Let’s go through the various components of IBC and its workings.
Chain A and Chain B: These represent two separate blockchain networks communicating with each other through the IBC protocol. Each has its own set of components (Application Module, IBC layers, and Light Client) to handle its side of the inter-chain communication.
Application Module: Each chain (Chain A and Chain B in the image) has an application module. This is the layer where the specific applications or functionalities of the blockchain are implemented. It’s where the business logic resides, and it interacts directly with IBC for cross-chain communications.
IBC/APP (Application Layer): This layer within the IBC architecture handles the application-specific logic that needs to be interpreted or executed as part of the cross-chain communication. It defines the rules and formats for the data being transferred between blockchains.
Data Packets: Are units of data that are transferred using IBC protocol. It includes payloads, header, smart contract calls and transfer messages. The packet could contain information about transfers, receivers address and amount.
Channels: Before initiating transactions between chains, channels must be established between ex. Coreum and Cosmos Hub. These channels establish parameters such as timeouts, packet ordering etc. Once a channel is created both chains open the channel by agreeing to the terms laid out in the channel via a handshake process. The chains then have the ability to initiate a transfer. In our case, for example, from Cosmos Hub specifying the amount in CORE, the denom of Coreum. Coreum in this example, is the destination chain.
IBC/TAO (Transport, Authentication, and Ordering Layer): This is the core of the IBC protocol, responsible for establishing and maintaining the connection between different blockchain networks. It ensures the data packets being transferred are authenticated, correctly ordered, and delivered securely.
Light Client: Each chain implements a light client of the other chain. A light client is a lightweight version of the blockchain that can verify its transactions and state without needing the complete history of the blockchain. In the context of IBC, light clients are used to verify the state of the counterparty chain without having to trust it completely.
Relayers: These are external services or agents that facilitate communication between the blockchains. They listen to events on both chains and relay (forward) messages and proofs between the chains. Relayers play a crucial role in the IBC ecosystem as they’re responsible for transferring data packets between the blockchains’ light clients. Anyone can operate a relayer; there are no specific qualifications required other than having the necessary infrastructure and resources to maintain the operation, including staying updated with both chains’ states and submitting transactions to them.
Chain A sends data to Chain B. It sends an IBC layer, which packages it into a format understood by Chain B. The packaged data is then handed to a relayer. The relayer forwards this data to the Light Client on Chain B, which validates the data using the IBC/TAO layer. Upon successful validation, the data moves up to the Application Module on Chain B, where it’s processed according to Chain B’s application logic.
For more information on IBC architecture or what IBC does please review these resources: Chapter Overview — The Inter-Blockchain Communication Protocol | Developer Portal (cosmos.network)
Exploring The Repo:
When we first get into our folder, this is what it should look like. We can see we have several components:
Let’s start by looking at our dedicated Coreum components, Coreum Signer and Coreum Signer Provider in the context folder under SRC.
Coreum signer is set up as a stargate signing client, we import the stargate library from cosmjs (a javascript library for interacting with cosmos sdk chains). Coreum signer will allow us to sign transactions with our wallet to the Coreum blockchain. Stargate is one of many cosmjs libraries to view more follow this link cosmos.github.io/cosmjs/
To see more of the of the modules we will be interacting with check out the modules folder
Let us now look at the config folder and view the defaults.ts file. Here we have the chain ID and public RPC points which are stored in our environment variables folder. If you copied the repo you will not see the .env file because it has been ignored by github in our gitignore file. Here is the .env file for additional reference.
Let’s look at the Header folder and check out the index.tsx file. This is where the connect wallet hookup is.
In the pages section within the app.tsx file we initiate the wallet connect functionality by wrapping our app in its components. Here we also import all the chains and wallet providers with which we can connect. Currently, we can connect with leapWallet, Keplr Wallet, Cosmostation wallet and frontier.
Now that you have some familiarity with the repo let’s start building out the main portion of this workshop, the IBC transfer component. First, let’s start by heading over toward the components folder and open it to the file called body. Now lets navigate to index.tsx. Look at the imports and make sure you have all your imports looking like this.
These are all the import modules we need in order for the ibc transfer functionality to work. Now let’s start building the application and look at our first function SendFTWithTheme(). We start by setting up multiple useState variables
Take a look at this line of code right here called chainContext
What we are doing here is importing from the config file in our defaults.ts file. If you look, you will see we are exporting a const variable called chainName which is equal to “coreum”. The useChain function is a cosmos kit module that allows connections to various cosmos chains. We also have something called walletAddress. This item is set to chainContext.address which again is equal to ‘coreum’. Then you will see two question marks which means that if the program is not able to get the address it will return empty. At the bottom of the function you will see the StdFee Module. Here we are importing the properties of standard fees which is a module in the cosmjs library. This allows us to specify the gas needed to make transfers.
Now let’s move on to creating our channels. In the same function create your code so it looks like this.
Here what we are creating is a filter to sort through chains and retrieve the channels from our ibc component which we get from the chain registry. In addition, we want to retrieve any channel that is == to “coreum.”
Then, in our second function which is called IBCEnableChains we map the channels. This function searches through a list of chain objects. Here is an image of what the chain objects look like.
Now we are going to return the chain object that we retrieved. In summary, all we are doing right here is returning all the chain resources for each individual chain we get. Below is the struct from which we are pulling this chain data.
You can see we have data such as description, network type, chain id and chain name. Finally, let’s create another useState for selecting our chains.
The next thing we are going to do is create a const variable with the coreumSigner and set it equal to useContext(CoreumSigner). This is an example of prop drilling, or passing data directly into our current component, in this case from our context folder where we have the coreumSigner script. Now lets create another const variable called msgBankSend. Make sure to put the fromAddress, where the transaction is from and the toAddress where the transaction is going to. Finally, set the the amount by declaring the denom, or the chain symbol and the amount which will be a string. Overall, the function constructs a message object for a Cosmos SDK bank transfer from one address to another. It specifies the type of the message, the sending and receiving addresses, and the amount and denomination of the currency to be transferred. This message can then be used in a transaction, signed, and broadcast to the blockchain network to execute the transfer.
Now lets create the function to actually trigger the sending of these tokens. It should look like the code below. Look at the send() function.
We have to call our coreumSigner in the send() function. Now we use the . operator to get the module signAndBroadcast and use our double question mark to once again check if the walletAddress is there or if it should return empty. We also call our bank send module along with the gas fee, which we specified earlier in this component. To explain, the coreum signer is our wallet which allows us to sign for and execute the msgBankSend function from cosmjs which permits us to transfer our tokens. We also have some logic to handle error functionality by returning the response as a promise, if the promise is not fulfilled we will catch and set the error.
Finally, we are going to create IBC Send which is the function that we are interacting with in the UI.
To explain, this function is essentially where the majority of the IBC functionality occurs. We import a module called Coin which is responsible for helping us specify the type of denom and the amount of tokens being sent. The height is essentially a reference to the block height. Long is used for numeric purposes to convert the string to a number. After we call the coreum signer and specify transfer as the operation we then list our selected channel name. Which we can manipulate in the UI. In summary, the IBCSend function encapsulates the process of preparing and executing an IBC token transfer, including setting up the transfer details, defining a timeout to ensure the transaction doesn’t hang indefinitely, and handling the response. The use of timeoutHeight is crucial for security and efficiency in cross-chain communications, ensuring that tokens are not stuck in limbo if network conditions change or if the destination chain does not accept the transfer in a timely manner.
Finally, the last thing we need to do to get our IBC module to work properly is create a function that dynamically constructs denoms. Here is what the code should look like.
We have to create a variable that will convert our denom and selected chain into a hash using crypto which allows us to convert it to the proper SHA256 hash. The function called handleButtonClick() it is used when we click the button. Then at the end we have useEffect to allow the handleButtonClick to dynamically update and change state whenever we click the button. Overall, what we are doing here is creating a hash of the channel name and denom of a specific chain. We do this dynamically as we click the button so that we can immediately make the transfer to our desired chain.
Here is a demo of what we just created
Now we are ready to dive into the UI very briefly. Most of the code for our UI can be found in the bottom section of this body component. It starts where you see the return parameter.
The first component we will look at is this IBC enable component which allows us to toggle the IBC functionality. Here is the code.
When you implement this functionality you get an effect like this with the UI
In regards to the main container we are using a component called ListBox from Headless UI. Headless UI is great for common, pre-made UI components and can save allot of time when it comes to coding your own work. Headless UI — Unstyled, fully accessible UI components
The listbox component gives us a drop down menu and different options we can plug in. In our case, we map through all the IBC chains that are in the array that we defined earlier in the tutorial.
Finally, to capture our data in this Listbox we are going to use a form. We will capture the denom, the amount and finally the receiver address.
Make sure to implement your buttons at the end for submitting this form and the data captured by our useState variables.
Now try sending your tokens using our newly built IBC component. You can verify your transaction here to see if it went through. Blockchain Explorer | Coreum
Check out more of Coreum workshops here: CoreumFoundation/workshops: All material to support the Coreum workshops (github.com)
For more documentation and understanding on IBC please reference these documentation links. Understand IBC Denoms | Developer Portal (cosmos.network)
🤝 Contributing
We welcome contributions! Feel free to submit PRs for improvements to the boilerplate.
📜 License
This project is open-source and available under a standard licence. Feel free to use and modify it as needed.
🙏 Acknowledgments
A big thank you to everyone involved in making this tutorial possible. Your efforts are greatly appreciated by the developer community.