Repository
https://github.com/igormuba/EthereumFrontEnd/tree/master/class3
What will I learn?
- React consultor and states
- Working with Remix/Ganache/Web3 to import contract ABI and address to React
- Creating and interacting with a contract instance on React with Web3
- Getting and formatting data returned by the blockchain
Requirements
- Chrome or Brave Browser
- Metamask browser extension
- Node/NPM
- Ganache
Difficulty
- Intermediary.
Introduction
On the previous tutorial of the series we saw can we connect our browser with a blockchain node using the framework web3.js, provided by Ethereum. By using Metamask as our node, we can easily switch between blockchains. That means you can test on a local emulated environment (like Ganache) or you can use a regular testnet (like Rinkeby or Ropsten), or even switch to the main Ethereum network!
Now, let us dive a bit on how to "see" contract. We can already connect to any Ethereum blockchain, but we need to know how to work with contracts. For this, I will use the code for an ERC20 contract we have made in another series. You can get the contract for this token in here. Just keep in mind that the token is not optimal, not fully ERC20 compatible and has security issues, it is just a very basic token implementation for testing purposes! I have other more in-depth tutorials regarding fully ERC20 compliance and how to improve security, but that is not the goal here.
We will leverage the simplicity of the Remix online Solidity IDE with the simulation of Ganache to deploy and run our contract locally.
Our contract
For web3.js to work with a contract, it needs two things:
- The ABI code of the contract
- The address of the contract.
The ABI is needed because it contains, in JSON, the functions and variables on the contract. Without it, web3.js wouldn't know what to do with the contract data, because they talk "different languages"! And the address is required so that the browser knows "where" in the blockchain to make the calls.
To get the contract ABI, you can use the Remix online Solidity IDE, this tool allows us to get the ABI and the address, even from our local Ganache environment! Here is the step by step to deploy.
Paste your code on the IDE. Save/compile it with ctrl+c on Windows/Linux/BSD or cmd+s on Mac:
On the top right corner select the "run" tab:
On the environment setting, choose "Web3 Provider", that allows us to use our local Ganache environment instead of Remix simulated Virtual Machine:
And insert the IP:Port of your local Ganache environment (or any other network you want, as long as it matches your Metamask network):
GIF illustrating the process:
Try to make sure that the address matches the IP/Port of Ganache (and Metamask!) so we can work on the same page:
Now you can deploy your contract by clicking on "deploy" on the run page:
Storing the contract details
Now, back to our code editor, since our work with Remix is done (don't close it yet! we need to store the data!). On the src
folder create a new file to store the address and the ABI of the contract. I will call this file "contract.js":
Inside it, I will export the variables with the needed data for the "app" to run on the browser. Here is how you can get that from Remix!
On the Remix compile tab, click on "ABI", this will copy all the ABI data to your clipboard:
On the contract.js
file, paste it on a variable that we can export, for example:
export let contract_abi = //PASTE THE ABI HERE!
On the "run" tab on Remix, you can copy the address by clicking on the clipboard icon:
You could also get the contract from Ganache on the tab "blocks" on the transaction that created the contract since we deployed it locally on a previous step:
Now, save the address on the save file as the ABI (for simplicity):
export let contract_address = 'PASTE THE ADDRESS HERE (WITH SINGLE QUOTES)'
The final file should look something like this:
React
Now that we have all that is necessary to interact with the contract, it is time to have fun with React.js! Let us dig on a few basic concepts and apply them to our small test with the contract.
First, we will need to use states to make variables globally available for all of our component. To do this we use a constructor to create a state. A state behaves similarly to a singleton. You create one and the variables inside it can be accessed for other methods inside our component.
In practice, to create one, we use the following syntax:
constructor(props){
super(props)
this.state = {
//here goes the global variables
}
}
The global variables will go and replace the comment.
In our case, we want to store the token balance of our user (ourselves). So replace the comment with:
balance: 0
Now, on the render method of the component, we can delete everything. It was showing the default react app webpage, but we don't need it. Instead, we will render:
render(){
return(
<div>
<p>Token Balance: {this.state.balance}</p>
</div>
);
}
The {this.state.balance}
will grab the balance
variable inside the state
object. At the moment, if you run the app, you will see just a zero on the webpage. To fill it with data, we need to our previous blockchainConnection
method and instantiate the contract and make a connection to it.
Connecting to the contract
To instantiate the contract, we need the ABI and the address from the contract.js
file. But they are on different files. So, on the top of the App.js
we import them with:
import {contract_address, contract_abi} from './contract'
The above imports both variables.
Now, on the blockchainConnection
method we can create the instance with:
let erc20token = new web3.eth.Contract(contract_abi, contract_address)
Now, if you check the contract, there is a method called balanceOf
that receives a wallet address as an argument. That method returns the token balance of said address. I will show you the full call and then explain the bits of it:
let myTokenAmount = await erc20token.methods.balanceOf('YOUR WALLET HERE').call()
This saves the returned token balance on the variable myTokenAmount
.
await
, as explained in other tutorials, tells JavaScript to hold the execution until we get a response because blockchains are inherently slow!
erc20token.methods
is where the method names are.
balanceOf('YOUR WALLET HERE')
receives the wallet of a user as an argument. Change the wallet to your own, remember, this must be the same wallet that deployed the contract! Else we will receive a zero!
call()
tells it that it is a blockchain call, calls don't consume gas and are free because are read-only!
Now, to store the result on the state, we do:
this.setState({
balance: myTokenAmount
})
The looks ok, but it is not. Let's see why by checking on the browser.
The behavior expected is: To open the page and display the token balance of the user (100).
What we get is:
This is because the types the blockchain return are not compatible with the types React expected. The type returned is an object:
To solve this, we simply need to parse the number as an int (a native JavaScript function) by adding parseInt
around the variable:
parseInt(myTokenAmount)
And that gives us the expected result:
That means we've hit gold and we have successfully talked with the contract!
Series curriculum
Beneficiaries
This post has as beneficiaries
- @utopian.pay with 5%
- @steempeak with 5%
using the SteemPeak beneficiary tool:
Thank you for another beautiful tutorial.
Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.
To view those questions and the relevant answers related to your post, click here.
Need help? Chat with us on Discord.
[utopian-moderator]
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Thank you for your review, @mcfarhat! Keep up the good work!
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Hi @igormuba!
Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Hey, @igormuba!
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!
Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).
Want to chat? Join us on Discord https://discord.gg/h52nFrV.
Vote for Utopian Witness!
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Hi, @igormuba!
You just got a 0.27% upvote from SteemPlus!
To get higher upvotes, earn more SteemPlus Points (SPP). On your Steemit wallet, check your SPP balance and click on "How to earn SPP?" to find out all the ways to earn.
If you're not using SteemPlus yet, please check our last posts in here to see the many ways in which SteemPlus can improve your Steem experience on Steemit and Busy.
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit