DEV Community


Posted on

Compile Solidity In The Browser

Like me, if you have run into issues using Browser-solc when trying to create an app that could compile solidity in the client using ReactJS, this article is for you. We'll see how to use of @agnostico/browser-solidity-compiler to acheive our result shortly, getting rid of common issues you are likely to face.

There are many reasons why you may want to compile a solidity smart contract in the browser; Maybe you are building the next remix or you are building an entirely different application and you simply want to have the client fully take control of what is compiled as with the case with what I am building, Agnostico.

Since the eth_compile API was deprecated, the available alternatives (Solc-JS and the extended Browser-Solc) work best in a server setup or is tightly coupled to the HTML DOM, they are not so flexible to work with in modern Javascript library environment such as ReactJS, well at least, not so straight-forward. This will make your application throw tantrums as you develop with them which, from my experience, is a terrible developer experience.

To allow others build their applications with ease, I built on the provisions of solcjs and created a package that can work efficiently in such development environments (and with typescript support). It uses webworkers under the hood to offload heavy compilation computations from our main thread. Let's take a look at it in action.

The project is available in the example branch of the repo. I will explain how it works here with snippets so let's get to it.

The example repository is built with create-react-app, and to install our package, we run

npm i @agnostico/browser-solidity-compiler

Using the package in our application,

// App.tsx
import {
} from '@agnostico/browser-solidity-compiler';
Enter fullscreen mode Exit fullscreen mode

the getCompilerVersions is an async operation that fetches the list of existing solidity versions from

// App.tsx
const loadVersions = async () => {
 const { releases, latestRelease, builds } = await getCompilerVersions()

// Load versions immediately page is mounted
useEffect(() => {
 (async () => { 
   await loadVersions() 
 }, []);
Enter fullscreen mode Exit fullscreen mode

Our returned object looks like this

Solidity Versions

And then to compile our contracts, we select the we simply pass the required arguments into the compiler object. Our version will look similar to this if we are not using a template literal: (If we are using solidity version 0.8.17). But to make it dynamic in cases where the user can switch between versions, we implement like this.

// App.tsx
const compiled = (await solidityCompiler({ 
version: `${usingVersion}`,
 contractBody: content,
Enter fullscreen mode Exit fullscreen mode

The contractBody is the string of the contract(s) to be compiled. while options the optimization object. It is optional. For example, you could have optimization looking like this

options.optimizer = {
  enabled: true,
  runs: 200,
Enter fullscreen mode Exit fullscreen mode

Our contracts in the example repo was returned in the compiled variable, stored in state and accessed this way

// App.tsx
Object.keys(compiledContract?.contracts?.Compiled_Contracts).map((cont) => (
  <div key={cont}>

  <span>Bytecode</span>: <small>
Enter fullscreen mode Exit fullscreen mode

The contract(s) are stored in a property of the returned object called Compiled_Contracts where we can access their information such as the abi or bytecode and shown above.


Top comments (1)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.