Building Smart Contract only DApps with Embark

Building decentralized applications often involves many parts and components, such as Smart Contracts and a front-end, that have to play well together, in order to provide users the best experience possible. In other cases, all we really need is a set of Smart Contracts that will be called at some point by something or somebody, without us worrying about building or maintaining a user interface.

Embark enables us to implement either of those scenarios and in this article we’re going to explore how to build a decentralized applications where Smart Contracts are the primary focus.

Creating a Smart Contracts only application

Before we get started, let’s make sure that Embark’s command line tool is actually installed. Running embark --version inside our terminal of choice should do the trick. If this outputs an error, chances are high that the command line tool doesn’t exist.

To change that, all we have to do is using Node’s package manager npm, using the following command:

$ npm install -g [email protected]

This will make Embark’s command line tool globally available on our machines. Notice that @next picks the latest development version of Embark. This release tag will be removed in the future once version 4.0.0 stable has been released (no worries, we’ll update this article accordingly).

If we don’t feel comfortable with that, we can omit the @next part and get the latest stable version instead, which at the time of writing this article was 3.2.7. However, we do recommend using the development version as it’s fairly stable and comes with tons of improvements, better performance and features.

For more information on installing Embark, check out our Installation Guide in the official documentation.

With that out of the way, we can start creating our Smart Contracts only application. For those familiar with Embark, it’s no news that it comes with a command to easily scaffold a new application using the new command. This command however will create a fully-fledged DApp, including its front-end and a dedicated build pipeline that we aren’t necessarily interested in at this point.

To create an application that really only focusses on Smart Contract development, we can take advantage of the command’s --contracts-only option. Let’s go ahead and do that. In this tutorial we’ll be creating a rather trivial project, namely a simple storage, so let’s call the project simple-storage:

$ embark new simple-storage --contracts-only 
$ cd simple-storage

Once Embark is done, we’ve got a new folder simple-storage in our current working directory that has everything we need to build a Smart Contract only decentralized application. After cd‘ing into it, we’ll see what the project’s structure looks like:

├── contracts/
└── test/
├── contracts.js
└── embark.json
└── package.json

This is really the least amount of files needed to start a new project that purely focusses on Smart Contract development. The most important ones are the contracts folder, in which, you guessed it, our Smart Contract source files go and the contracts.json file, in which we configure how the Smart Contracts are deployed.

For a more detailed description about every possible application file generated by Embark, head over to our Application Structure documentation.

Creating and deploying Smart Contracts

Let’s go ahead and create a simple Smart Contract to dive a bit deeper into how it can be configured for deployment. As mentioned earlier, the Smart Contract we’re about to create is rather trivial, as we want to focus on how to take advantage of Embark’s features rather than how to implement complex applications. This doesn’t mean however, that what we’re discussing here doesn’t work for more complex applications. Everything we do here, you can do in with any other DApp!

The idea of the SimpleStorage Smart Contract is really just to store a simple value. All we need are methods to set and get that value:

pragma solidity ^0.5.0;

contract SimpleStorage {
  uint public storedData;

  constructor(uint initialValue) public {
    storedData = initialValue;
  }

  function set(uint x) public {
    storedData = x;
  }

  function get() public view returns (uint retVal) {
    return storedData;
  }

}

We put this Smart Contract into ./contracts/simple-storage.sol. Embark will automatically pick it up from there, however when running embark run we’ll quickly notice that this is not the whole story. Here’s what Embark will output:

“[SimpleStorage]: Error: attempted to deploy SimpleStorage without specifying parameters. Check if there are any params defined for this contract in this environment in the contracts configuration file.”

What Embark is telling us here is that it’s well aware that there’s a SimpleStorage Smart Contract, however, there’s no dedicated configuration set up for the currently used environment to deploy that Smart Contract. Environments are an essential feature of Embark that lets us have deploying Smart Contracts behaving differently per environment if we want to.

Let’s open our project’s contracts.js file and head down to the contracts section:

...
contracts: {
  // example:
  //SimpleStorage: {
  //  args: [ 100 ]
  //}
}
...

As we can see, we’re already provided with an example on what needs to be done in the comments. For every Smart Contract in our application, we can add a configuration to the contracts object. Embark is very flexible when it comes to deployment configuration of contracts, so we recommend you checking out the Smart Contract Configuration Guide.

For now, let’s just take the suggested example in the comments and set the constructor parameter of SimpleStorage:

SimpleStorage: {
  args: [ 100 ]
}

If our Smart Contracts happens to have more constructor parameters, we can simply add more values to args in the same order. Sometimes, this gets a little too complex though. Embark supports named parameters as well for those cases:

SimpleStorage: {
  args: { initialValue: 100 }
}

Having that set up, we can execute embark run again, which should result in a successful deployment of our Smart Contract.

Deploying contracts
deploying SimpleStorage with 143503 gas at the price of 1 Wei, estimated cost: 143503 Wei (txHash: 0x68d7bfb359da8614b9231915404095282e1943741af148bde39fc987ac6706f3)
SimpleStorage deployed at 0xa3bbd48f1A398fb355E69C73B9dC77f77959FB14 using 139768 gas (txHash: 0x68d7bfb359da8614b9231915404095282e1943741af148bde39fc987ac6706f3)
Finished deploying contracts

Embark not only tells gives us the transaction hash of the deployment for SimpleStorage as soon as possible, it also gives us the estimated and confirmed cost of the transaction.

Try it yourself!

Interacting with Smart Contracts using Embark’s console

Another powerful feature we shouldn’t forget is Embark’s console. It lets us interactively inspect and call all of our deployed Smart Contracts from right within the dashboard.

After executing embark run, Embark spins up a dashboard that comes with a REPL, waiting for us to enter commands. To get an idea of what commands are available, run the help command and see what happens:

Embark (development) > help

The output should look something like this (keep in mind that this might look different on your machine, depending on what version of Embark’s command line tool you’re using):

Welcome to Embark 4.0.0-beta.0

possible commands are:
ipfs - instantiated js-ipfs object configured to the current environment (available if ipfs is enabled)
swarm - instantiated swarm-api object configured to the current environment (available if swarm is enabled)
web3 - instantiated web3.js object configured to the current environment
EmbarkJS - EmbarkJS static functions for Storage, Messages, Names, etc.
log  on/off - Activate or deactivate the logs of a sub-process. Options: blockchain, ipfs, webserver
versions - display versions in use for libraries and tools like web3 and solc
profile  - Outputs the function profile of a contract
debug  - Debug the last transaction or the transaction specified by a hash
    next/n - During a debug, step over forward
    previous/p - During a debug, step over back
    var local/v l/vl - During a debug, display local variables
    var global/v g/vg - During a debug, display global variables
    var all/v a/va - During a debug, display all variables
history  - display console commands history
token - Copies and prints the token for the cockpit
api start/stop - Start or stop the API
plugin install  - Installs a plugin in the Dapp. eg: plugin install embark-solc
quit - to immediatly exit (alias: exit)

The web3 object and the interfaces for the deployed contracts and their methods are also available

One thing that the console’s help doesn’t tell us, is that each and every of our deployed Smart Contracts is available as descriptive JavaScript object. Simply enter the name of your Smart Contract and Embark will output its structure, properties and methods:

Embark (development) > SimpleStorage

In fact, we can go ahead and execute the Smart Contract’s methods if we want to! For example, if we want to confirm that the constructor parameter for initialValue was indeed set to 100, we can simply call SimpleStorage‘s get method like this:

Embark (development) > await SimpleStorage.method.get().call()

Notice that the await keyword is needed to resolve the requested value. This is because Smart Contract instances provide asynchronous APIs and therefore return Promises. await ensures that it unwraps the request value once it resolves.

Where to go from here

Obviously we’ve only touched the tip of the iceberg when it comes to Embark’s built-in features. We highly recommend checking out all of the guide in our official documentation, as it covers all of the important commands, options and features a DApp developer needs in her day-to-day job.

Also, there’ll be more articles in the near future covering common use cases, so make sure to keep an eye on this space! And last but not least, if there’s anything you miss in Embark, make sure to talk to us in our chatroom so we can discuss what we can do to improve the tooling you need!