(PT 3) Ethereum Front End - Interacting With A Smart Contract From The Browser (Part 3)

in #utopian-io5 years ago

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:
Captura de Tela 20190410 às 16.37.36.png

On the top right corner select the "run" tab:
Captura de Tela 20190410 às 16.39.41.png

On the environment setting, choose "Web3 Provider", that allows us to use our local Ganache environment instead of Remix simulated Virtual Machine:
Captura de Tela 20190410 às 16.40.15.png

And insert the IP:Port of your local Ganache environment (or any other network you want, as long as it matches your Metamask network):
Captura de Tela 20190410 às 16.41.04.png
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:
Captura de Tela 20190410 às 16.42.00.png

Now you can deploy your contract by clicking on "deploy" on the run page:
Captura de Tela 20190410 às 17.08.26.png

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":
Captura de Tela 20190410 às 17.11.03.png

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:
Captura de Tela 20190410 às 17.13.03.png

On the contract.js file, paste it on a variable that we can export, for example:

export let contract_abi = //PASTE THE ABI HERE!

Captura de Tela 20190410 às 17.14.44.png

On the "run" tab on Remix, you can copy the address by clicking on the clipboard icon:

Captura de Tela 20190410 às 17.15.26.png

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:
Captura de Tela 20190410 às 17.16.44.png

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:
Captura de Tela 20190410 às 17.18.07.png

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:
Captura de Tela 20190410 às 18.02.12.png

This is because the types the blockchain return are not compatible with the types React expected. The type returned is an object:
Captura de Tela 20190410 às 18.03.15.png

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:
Captura de Tela 20190410 às 18.04.56.png

That means we've hit gold and we have successfully talked with the contract!

Series curriculum

-Part 2
-Part 1

Beneficiaries

This post has as beneficiaries

using the SteemPeak beneficiary tool:
captura4.png

Sort:  

Thank you for another beautiful tutorial.

  • I had no idea you can do that via a browser.
  • Good basic intro into the concept of fetching data from contact and communicating with them.
  • Very good work on screenshots and illustrations.

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]

Thank you for your review, @mcfarhat! Keep up the good work!

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

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!

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.

Coin Marketplace

STEEM 0.36
TRX 0.12
JST 0.040
BTC 70846.59
ETH 3567.69
USDT 1.00
SBD 4.79