Executing smart contracts in your browser using Truffle, Ganache, Browserify, and Web3
The opinions stated here are my own, not those of my company.
There are a variety of tools to build a blockchain-based web app. For example, you can see a simple banking app below:
These contracts were written in Solidity and executed through Truffle. While I could verify they worked, getting them to run in a browser environment was hard. In fact, there is basically no documentation on the integration of these technologies.
This blog post gives you a setup of everything together, but does not go into the specifics of building a simple bank. Instead this will be for a more generic example.
Let’s say you already have your
MyContract.sol Solidity contract. Use Truffle to deploy it to your blockchain network. In my case, I am using Ganache. This runs locally (on port
When you run the
truffle migrate command, take note of several properties of the output.
$ truffle deploy
> transaction hash: 0x562f463faa3666e948a08ea96f96ae239aff9f48298f6096ecbd09404903027e
> Blocks: 0 Seconds: 0 > contract address: 0x941F4963540B1df054343d115767B9cb3E3cDc3D
> block number: 3
> block timestamp: 1617929065
> account: 0xA866B5C54e06fF40cA96d93b7B7FaE1809D0d858
> balance: 99.98373884
> gas used: 390433 (0x5f521)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.00780866 ETH > Saving migration to chain.
> Saving artifacts
> Total cost: 0.01626116 ETH
Save the contract address and account address. Since we’ll be using a web browser, create a new
index.js file and save these as constants:
package.json file in our root project directory to install our dependencies. NPM can use package files to define your project and what it needs. It allows us to define dependencies and build scripts in a single file for greater convenience. This file is used in the industry.
Be sure to run
npm install to download everything.
Note that, when Truffle builds your contracts, there is created a
build/contracts/MyContract.json. Take note of this file, we’ll be using it later.
Setting up Web3
index.js into a
bundle.js that can run in a browser.
This is what the
scripts.build field in
package.json means. When you run
npm run build, we execute that command.
To connect to our Ganache network, we can add a single line to our
To aid debugging, I recommend setting up
window.web3 = web3 in your
index.js as well. This will let you more effectively debug and execute commands in browser DevTools.
How do we know this worked? Let’s add an element to display our account & balance with an
index.js file with an event listener. When the page loads, execute the
updateBalance function. By extracting this to a separate function, we can call this in response to contract execution.
bundle.js and open
index.html in the browser. You should see the address and balance appear automatically on the screen.
If you have made it to this point, you’ve successfully setup Web3.
Setting up contracts
Now that we’ve connected to Web3, let’s connect to the contract itself. Here is where our previously created JSON file will be handy.
The Web3 contract instantiation requires the contract ABI, which is part of the larger JSON bundle. We also pass in the contract address we obtained earlier:
Note that I am note entirely sure that my use of
defaultAccount is accurate here. But my code does work so I won’t complain.
Now our contracts should be in our execution environment, so we can start executing contracts.
Executing smart contracts
There are generally two kinds of smart contract commands: calls and sends. A call is generally mapped to a
view in Solidity: a method that doesn’t involve a transaction. This may be seen as a “getter”. Sends actually create a transaction and change the contract state, like a Solidity
We can see some of each in our contract. First let’s add a button and a label for our response on the webpage:
You can see the entire process play out in the click event listener on the button. We also disable it during execution as a way of debouncing.
We send an event with our account and a hard-coded value. Later we can call a second method to read the balance and display on the page.
There are a number of asynchronous operations here. Reading the guide on Promises from Mozilla will provide a good background here.
Along my development path, I came across an obscure error when trying to do anything with my contract:
Error: Returned values aren’t valid, did it run Out of Gas? You might also see this error if you are not using the correct ABI for the contract you are retrieving data from, requesting data from a block number that does not exist, or querying a node which is not fully synced.
It took me some time to ascertain why this was happening. Googling the error did not provide a single answer. It turned out that my contract address was wrong. I needed to use the one from Truffle and not my wallet address from Ganache.
I hope this guide helps you at least get started. As this programming environment is new, there are scant resources. While some tools may have their own docs, there isn’t much in the way of integration guides.
This is what I got from my own experience and development rather than any insider information on any tool. Of course, at the rapid pace of development, this post may be quickly obsolete.