Executing smart contracts in your browser using Truffle, Ganache, Browserify, and Web3

Nick Felker
Apr 11 · 5 min read

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:

Simple Bank on the web, with deposit/withdraw smart contracts

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.

Truffle

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 7545).

When you run the truffle migrate command, take note of several properties of the output.

$ truffle deploy

Replacing 'MyContract'
----------------------
> transaction hash: 0x562f463faa3666e948a08ea96f96ae239aff9f48298f6096ecbd09404903027e
> Blocks: 0 Seconds: 0

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:

Create a 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

Web3 is essentially the binding between the Ganache test network and your smart contracts. It lets you access your accounts and execute contracts in a Node environment.

Note that a Node environment is different from a browser environment in subtle but important ways even though they both run JavaScript. We can use a tool like Browserify to transpile our 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 index.js :

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.

You can execute commands directly in DevTools to get a feel for them

How do we know this worked? Let’s add an element to display our account & balance with an index.html file:

Update our 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.

Now regenerate 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.

Note that again we are binding the object to the window (objects in JavaScript are pass-by-reference) to help debug commands right in the console.

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 payable.

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.

Troubleshooting

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.

Join Coinmonks Telegram Channel and learn about crypto trading and investing

Also, Read

Coinmonks

Coinmonks is a non-profit Crypto educational publication.