LiquidApps DAPP Network Walkthrough #1: Zeus and vRAM

Setting Up Zeus SDK & Adding vRAM to Your Smart Contract

DAPP Network
The DAPP Network Blog
6 min readAug 19, 2019

--

Since you’re here, you’ve probably heard about the DAPP Network, as well as vRAM and other services the Network can provide. In this series, we’re walking you through the process of using DAPP Network services in a distributed application, in order to unlock a host of features that could not be previously added in a decentralized way.

The Zeus SDK is the primary way to enable your dApp to take advantage of the services provided by DAPP Service Providers (DSPs) on the DAPP Network. As of this writing, 13 unique DSPs are offering 34 packages on the EOS mainnet, most of them vRAM services.

This is the first article in a series of technical walkthroughs. We’ll explain how to take advantage of other services in future articles — including web and cross-blockchain oracles (LiquidOracles), CRON scheduled tasks (LiquidScheduler), randomness, and virtual accounts (LiquidAccounts). In order to prepare for those services, though, we need to learn our way around Zeus.

Zeus is a simple, extensible development framework that allows dApp developers to integrate DAPP Network products and features with minimal smart contract code.

Note: This walkthrough contains a large number of terminal commands. Do not type or copy/paste the $ at the beginning of each line — it just indicates where the next command begins.

(Optional) Setting Up and Using NVM

You may already be using NVM, Node Version Manager, to manage your Node.js development. If not, it’s recommended you do so, as it will allow you to use whatever version of node you need for any given application.

Note: Homebrew install is not recommended for NVM.

If you’re on macOS, you might be prompted to install Xcode Command Line Tools during the following process.

$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash$ export NVM_DIR="$HOME/.nvm"
$ [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
$ [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"

The currently recommended Node.js version for the Zeus SDK is 10.x (currently 10.15.3). Let’s instruct NVM to install this version:

$ nvm install 10
$ nvm install-latest-npm

Installing Zeus Prerequisites on Linux

On Linux, you may need to install some prerequisites:

Ubuntu/Debian:

$ sudo add-apt-repository ppa:ubuntu-toolchain-r/test$ sudo apt update
$ sudo apt upgrade -y libstdc++6
$ sudo apt install -y make cmake build-essential python

Centos/Fedora/AWS Linux:

$ sudo yum install -y make cmake3 python git gcc-c++ wget
$ export CMAKE_PREFIX_PATH=/usr/opt/eosio.cdt/1.6.1/lib/cmake/eosio.cdt

Centos/Fedora additional commands:

$ wget https://github.com/Kitware/CMake/releases/download/v3.14.3/cmake-3.14.3.tar.gz
$ tar xvfx cmake-3.14.3.tar.gz
$ cd cmake-3.14.3
$ ./bootstrap
$ gmake
$ sudo make install
$ cd ..

Installing and Deploying Zeus

Installing Zeus with the -g flag installs it globally:

$ npm install -g @liquidapps/zeus-cmd

However, even though we’re installing Zeus globally, only zeus unbox will function globally.

Commands such as zeus test, zeus migrate, and zeus compile are extensions that are only recognized when the local project directory is the site of an unboxing.

Once Zeus has finished installing, we can unbox and test the helloworld contract to make sure everything is in order. Navigate to the directory you’d like Zeus to unbox to, then run the following:

$ zeus unbox helloworld
$ cd helloworld
$ zeus test

zeus unbox will place numerous directories and the zeus-box.json inside a helloworld directory.

The Zeus SDK comes with a number of other sample deployments, such as vRAM examples coldtoken, deepfreeze, vgrab, cardgame, and registry, as well as microauctions, eos-detective-reports, token (a deployment of the standard eosio.token contract), and more. Reference contracts for newer services are also included.

Adding vRAM to Your Smart Contract

Now that we’ve set up the Zeus SDK, we can begin using it for our EOSIO development. Let’s take a look at what adding vRAM to the Elemental Battles tutorial entails. For reference, you can grab the completed Elemental Battles code without vRAM here.

Let’s run zeus unbox cardgame.

Assuming you’re still in your helloworld directory:

$ cd ../
$ zeus unbox cardgame
$ cd cardgame

The final portion of the output from zeus unbox gives us some helpful direction as to what we can do next:

(OUTPUT)Enter new directory:
cd cardgame
Please try these sample commands:
⭐Deploy contract: zeus migrate
⭐Run frontend locally: zeus run frontend main
⭐Build frontend: zeus build frontend main
⭐Deploy frontend: zeus deploy frontend main
⭐Deploy and register frontend: zeus deploy frontend main — ipfs — register cardgame1111

Running a few commands will compile and migrate the contract, then open your frontend (localhost:3015):

$ zeus migrate && zeus run frontend main

To understand how this contract was converted into a vRAM-enabled one, let’s take a look at the cardgame.hpp file.

Adding vRAM doesn’t even require any changes to our cardgame.cpp or gameplay.cpp files, only our cardgame.hpp file.

Note: the code from the unboxed cardgame contract may contain additional features not covered in this tutorial. They will be addressed in later walkthroughs.

$ cd cardgame/contracts/eos/cardgame
$ nano cardgame.hpp

We can see that a number of simple steps have been followed to add vRAM. A few side notes are included with them, in case you’re unaware of some recent changes to the EOS CDT.

1) First of all, below the standard #include <eosio/eosio.hpp>, we see the libraries needed for the vRAM DAPP Service being imported, along with a number of new preprocessor directives:

Side note: until CDT 1.7, and still in the original Elemental Battles code, #include <eosio/eosio.hpp> was instead #include <eosiolib/eosio.hpp>. The latter is now deprecated.

#include "../dappservices/multi_index.hpp"
#define DAPPSERVICES_ACTIONS() \
XSIGNAL_DAPPSERVICE_ACTION \
IPFS_DAPPSERVICE_ACTIONS
#define DAPPSERVICE_ACTIONS_COMMANDS() \
IPFS_SVC_COMMANDS()
#define CONTRACT_NAME() cardgame

If we needed additional services, we would reference them here. For example, if this contract needed vRAM and oracle services:

/* ORACLES EXAMPLE ONLY
NOT FOR VRAM */
#include "../dappservices/multi_index.hpp"
#include "../dappservices/oracle.hpp"
#define DAPPSERVICES_ACTIONS() \
XSIGNAL_DAPPSERVICE_ACTION \
IPFS_DAPPSERVICE_ACTIONS \
ORACLE_DAPPSERVICE_ACTIONS
#define DAPPSERVICE_ACTIONS_COMMANDS() \
IPFS_SVC_COMMANDS() \
ORACLE_SVC_COMMANDS()
#define CONTRACT_NAME() cardgame

We’ll cover the use of services beyond vRAM in subsequent articles.

2) After all of our directives, including using statements, we tell Zeus that our contract proper is beginning:

CONTRACT_START()

3) We modify the typedef for our “users” table to a dapp::multi_index type. This is the table accessed by the contract’s many references to its only table, users_table _users. In the original code, this was a typedef of type eosio::multi_index. By using the drop-in dapp::multi_index replacement, we enable vRAM for this table.

Side note: in case you’re unaware, the syntaxes name(“users”) and “users”_n are equivalent.

typedef dapp::multi_index<name("users"), user_info> users_table;

4) To enable support for queries on the client side, we also add a new “.users” table using the same user_info struct, and a “users” table now defined by a shardbucket struct:

typedef eosio::multi_index<".users"_n, user_info> users_table_v_abi;TABLE shardbucket {
std::vector<char> shard_uri;
uint64_t shard;
uint64_t primary_key() const { return shard; }
};
typedef eosio::multi_index<"users"_n, shardbucket> users_table_abi;

Side note: in the original Elemental Battles code, struct[[eosio::table]] is used instead of TABLE. These are equivalent; the latter is a macro that the compiler converts to the former.

5) Finally, we’ll modify our EOSIO_DISPATCH macro at the end of the file just a bit, to a CONTRACT_END() closing our CONTRACT_START() from earlier:

CONTRACT_END((login)(startgame)(playcard)(nextround)(endgame))

Now, Zeus can compile our smart contract into a vRAM-enabled dApp. Note that secondary indices are not currently supported for use with vRAM.

As before, we can now deploy our contract to a local testnet and DSP for testing:

$ zeus migrate && zeus run frontend main

For more information, visit the growing LiquidApps documentation page, and if you have any questions, please ask on our Telegram developers channel.

In the next article, we’ll stake DAPP to a DAPP Service Provider on the Kylin testnet and launch our vRAM-enabled dApp there, and also discuss how to launch on the EOS mainnet. Follow LiquidApps to catch the rest of the series and learn how to effectively use the whole suite of the DAPP Network’s available services.

Follow LiquidApps

Website | Twitter | Telegram | LinkedIn | Github

Please click here to read an important disclaimer.

--

--

DAPP Network
The DAPP Network Blog

DAPP Network aims to optimize development on the blockchain by equipping developers with a range of products for building and scaling dApps.