mirror of https://github.com/embarklabs/embark.git
185 lines
10 KiB
Markdown
185 lines
10 KiB
Markdown
title: Building Smart Contract only DApps with Embark
|
|
author: pascal_precht
|
|
summary: "In this article we're going to explore how to build applications with Embark that focus purely on Smart Contract development. Read on!"
|
|
categories:
|
|
- tutorials
|
|
layout: blog-post
|
|
alias: news/2019/01/22/building-smart-contract-only-dapps/
|
|
---
|
|
|
|
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 embark
|
|
```
|
|
|
|
This will make Embark's command line tool globally available on our machines. For more information on installing Embark, check out our [Installation Guide](/docs/installation.html) 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](/docs/structure.html) 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](/docs/environments.html) 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](/docs/contracts_configuration.html).
|
|
|
|
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<ENTER>
|
|
```
|
|
|
|
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
|
|
|
|
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 <process> 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 <contractName> - Outputs the function profile of a contract
|
|
debug <txHash> - 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 <optionalLength> - display console commands history
|
|
token - Copies and prints the token for the cockpit
|
|
api start/stop - Start or stop the API
|
|
plugin install <package> - 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<ENTER>
|
|
```
|
|
|
|
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()<ENTER>
|
|
```
|
|
|
|
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](/docs), 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](https://gitter.im/embark-framework/Lobby) so we can discuss what we can do to improve the tooling you need!
|
|
|
|
|