paint-brush
How To Set Up An RSK Project Using Truffle And Open Zeppelinby@rootstock_io
489 reads
489 reads

How To Set Up An RSK Project Using Truffle And Open Zeppelin

by RootstockSeptember 1st, 2020
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

How To Set Up An RSK Project Using Truffle And Open Zeppelin Smart Contract Platform On Top of Bitcoin? In this tutorial, we will show you step-by-step how to create a new blockchain project. We will use a local node running locally to connect to the RSK testnet. We’ll also use a wallet mnemonic to set up a smart contract using Trufle. We'll need Java 8 in order to run RSK, which comes with Git Bash bundled. You will need Node.js and NPM (Java Package Manager)

People Mentioned

Mention Thumbnail
Mention Thumbnail

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - How To Set Up An RSK Project Using Truffle And Open Zeppelin
Rootstock HackerNoon profile picture

In this tutorial, we will show you step-by-step how to create a new blockchain project, using the Truffle framework and Open Zeppelin smart contracts library, connected to an RSK local node or RSK testnet.

RSK is an open-source platform for Ethereum compatible smart contracts based on the Bitcoin network. 

It does not matter whether you are an experienced developer, or just learning to code, you do not need to be a blockchain expert to follow along.

Overview

Here is a summary of the steps to be taken to build our project:

  1. Installation requirements;
  2. Run a RSK local node;
  3. Initialize a project using Truffle;
  4. Install Open Zeppelin smart contracts in our project;
  5. Install HD wallet provider;
  6. Create a wallet mnemonic;
  7. Configure Truffle to connect to RSK networks;
  8. Use Truffle console;
  9. Get some testnet R-BTCs from the RSK faucet;

Requirements

  • POSIX compliant shell
  • Curl
  • Java
  • Node.js and NPM (Node Package Manager)
  • Code editor: Visual Studio Code (VSCode) or any other editor of your choice
  • Truffle

POSIX compliant shell

The Portable Operating System Interface (POSIX) is a family of standards specified by the IEEE Computer Society for maintaining compatibility between operating systems. POSIX defines the application programming interface (API), along with command-line shells and utility interfaces, for software compatibility with variants of Unix and other operating systems. Source: Wikipidia

cURL

This is a system command that is likely already installed on your system, which allows you to make network requests, such as HTTP requests, from your command line.

If curl --version displays an error, download curl.

Java

You will need Java 8 in order to run RSKj.

Check if you already have Java installed:

java -version

If the above command displays an error or displays a version other than 1.8, you will need to install it.

Go to the official Java download page, download, and run the installer from there.

Node.js and NPM

Node.js and NPM are needed, though both are usually installed at once.

NB: To check if Node.js and NPM are already installed, input the following commands in the terminal:

node --version
npm --version

If you got an error, go to Node.js to install it.

Note that NPM is usually installed together with Node.js, so after installing Node.js, there’s no need to install it separately.

If you want to have more than one version installed, the most fuss-free way to install and manage multiple versions of the node on your computer is nvm.

Code editor

We need some software that is able to edit text files. Preferably one that has support for syntax highlighting for both Solidity and Javascript.

In this tutorial, we will use VS Code to create our project, you can download it here.

Verify if your VS Code installation was successful by typing the following command into the terminal:

code -v

Truffle

Truffle is a popular development framework with a mission to make smart contract development easier for developers. Amongst its features, it has a smart contract lifecycle management, scriptable deployment & migrations, automated contract testing, and simple network management.

It also makes developing on RSK easier, with the ability to configure custom networks for RSK.

To install Truffle, input the command below into the terminal and press enter at your project location:

npm install -g truffle

When the installation is finished, close the terminal, open it again and check the Truffle version:

truffle version

RSK regtest (Local node)

When we develop a project using Truffle Framework, we need a blockchain node running locally. This is better for development and running tests. We’ll connect to the RSK network via this local node.

There are several ways to set up an RSK local node. Here, we will download a JAR file and run it using the Java SDK that has been installed.

Download

Go to the releases page and click on the most recent to download it.

You need to click on the JAR file, at the end of the post about the latest release. Its name should be rskj-core-*.jar

Verify authenticity

When installing and running the RSKj node, it is always a good idea to verify that your copy is legitimate.

In the folder where you download the JAR file, go to a POSIX terminal and run this command:

sha256sum rskj-core-2.0.1-PAPYRUS-all.jar

For this version, it looked like this:

Note that if you are using Windows, you will need a POSIX compliant shell for this. See instructions about using Git Bash above.

For more information about verifying that your copy is legitimate, including signature verification, check out the full instructions on how to do this.

Run

To run the node:

java -cp <PATH-TO-THE-RSKJ-JAR> -
Drpc.providers.web.cors=* co.rsk.Start --regtest

(Replace with your path to the JAR file).

I am using a Windows OS and I saved the file at C:\RSK\node, so for me the full path is C:\RSK\node\rskj-core-2.0.1-PAPYRUS-all.jar.

The commands required to run the RSK node are:

On Windows terminal

java -cp C:\RSK\node\rskj-core-2.0.1-PAPYRUS-all.jar -
Drpc.providers.web.cors=* co.rsk.Start --regtest

Using Git Bash

java -cp C:/RSK/node/rskj-core-2.0.1-PAPYRUS-all.jar -
Drpc.providers.web.cors=* co.rsk.Start --regtest

On Linux and Mac

java -cp ~/RSK/node/rskj-core-2.0.1-PAPYRUS-all.jar -
Drpc.providers.web.cors=* co.rsk.Start --regtest

If you see no output - that is a good thing: Its output is directed to a log file.

Note the flag provided above: -Drpc.providers.web.cors=* This disables cross-origin resource sharing protection, effectively allowing any web page to access it. As we want to make JSON-RPC requests from a browser, such as a DApp, we need this flag.

This is the result in the terminal in Windows OS:

Important

Do not close this terminal/console window, if closed the local node will stop running.

Check if the node is running using cURL

Open a new terminal window.

Issue a JSON-RPC request to the RSK node’s HTTP server.

This is an example using cURL:

curl localhost:4444/1.1.0/ -X POST -H "Content-Type: application/json" 
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'

The response should look similar to this:

{"jsonrpc":"2.0","id":1,"result":"0x2991b"}

The result property is the number of the latest block that has been synced. Note that this value (0x2991b) is the block number in hexadecimal (base 16), so the output above indicates that the current block number is 170267 in decimal (base 10).

RSK Testnet - verify the connection

In addition to using the local node, we want to publish smart contracts to the testnet. Before it, let’s check if the connection is working.

This is an example using cURL. Enter the following command into your terminal.

curl https://public-node.testnet.rsk.co/2.0.1/ -X POST -H "Content-Type: 
application/json" --data
'{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'

This is a very simple query that simply asks what the latest block number is. You should receive a response similar to the following:

{"jsonrpc":"2.0","id":1,"result":"0xc3f9b"}

The result field is presented in hexadecimal. 0xc3f9b is the block number, and it’s decimal equivalent is: 802715. You can consult the testnet explorer and verify that it is the same result for block number.

Initialize a Truffle project

We have two options for initializing a project:

An empty project

A project based in a Truffle Box

1 - Initialize an empty Truffle project

Create a new folder. For example, myproject, and navigate to the folder in the terminal.

mkdir myproject
cd myproject

For example, I will create a folder at this location: C:\RSK\ (I’m using Windows).

My project can be located in the folder C:\RSK\myproject.

In your project folder, start an Truffle project by typing the command below into the terminal:

truffle init

Open the folder in VS Code to view the file structure like this:

./contracts: All our smart contracts will be stored in this folder.

./migrations: Deployment scripts will be stored in this folder.

./test: Test scripts will be stored in this folder.

./truffle-config.js: This is Truffle’s configuration file used to configure networks, including RSK networks.

Note that the following files were also created:

Migrations.sol: Keeps track of which migrations were done on the current network.

1_initial_migration.js: Deployment instructions for Migrations.sol.

Initialize an npm project

When we initialize an empty Truffle project, we also need to initialize an npm project.

Start an npm project in the myproject folder by typing the following commands below into the terminal:

npm init -y

2 - Initialize a project based in a Truffle Box

Note: Only do this if you have not done option 1.

Truffle Boxes are templates. In addition to Truffle, Truffle Boxes can contain other helpful modules, such as Solidity smart contracts, libraries, front-end views, and more.

In option 1, when we use truffle init, we used a special kind of truffle box. Check out other boxes.

Also we have some of them already configured for RSK, check it out here.

Install Open Zeppelin

Open Zeppelin Contracts is a set of libraries of Solidity smart contracts for Ethereum and other blockchains. These libraries will install not only the main libraries required for our token, but also libraries for ownership, safe math, and many other utilities. It’s worth mentioning that these libraries have been reviewed and audited to accomplish high standards of security, so contracts that depend on them are less susceptible to hacking when used correctly.

In the terminal, inside myproject folder, install Open Zeppelin libraries using this command:

npm install -E @openzeppelin/contracts@2.5.0

The option -E is to save dependencies with an exact version rather than the latest version published on npm.

Some contracts may change over time, so it is important to set the version. This tutorial was written using this specific version.

Install HD wallet provider

To connect to the RSK network, we are going to use a provider that allows us to connect to any network by unlocking an account locally. We are going to use @truffle/hdwallet-provider. This can be used to sign transactions for addresses derived from a 12 or 24 word mnemonic.

You need to have Node >= 7.6 installed.

In the terminal, inside the myproject folder, install the HD wallet provider with this command:

npm install -E @truffle/hdwallet-provider@1.0.34

This truffle package comes with many dependencies, and so can take a long time to complete. A successful installation message is shown if everything works fine.

Create a wallet

To use testnet, we need tR-BTC and an address to store them. The best way is to create a wallet from a mnemonic, using the pattern defined at BIP39

There are a few ways to do this.

One is to create using a web wallet, such as Metamask or Nifty wallet. These wallets generate the mnemonic for you. If you wanted to create using Metamask, you can get the instructions here:

using Remix and Metamask with RSK testnet

iancoleman.io/bip39

Another way is using this web app:

iancoleman.io/bip39

Note: In this tutorial, the method used to store the mnemonic is not recommended to be used for any ‘real’ wallet because it’s not secure enough to generate a private key in a website, however we will use this here for learning purposes, and because we’re using the Testnet, so no real amounts are at stake.

In the Generate a random mnemonic field, select 12 words and click on the generate button.

The result appears in the BIP39 Mnemonic field. They should be 12 random words like the words in the image:

My mnemonic is:

energy knife ice mouse merge track cram brown decorate atom rule virus

Copy these 12 words, we’ll use it later in this tutorial.

mnemonics module

Another alternative is using package mnemonics, which is a simple utility that can be used to generate BIP39 mnemonics.

To install mnemonics globally, input the command below into the terminal and press enter at your project location:

npm install -g mnemonics@1.1.3

Use this to generate a 12-word BIP39 mnemonic, by entering this command:

mnemonics > .secret

This saves a new mnemonic in the file named .secret, which is the next step.

Create .secret file

In the terminal, inside the myproject folder, create a file named .secret.

Do you remember your mnemonic? Paste your mnemonic in this file and save it.

Configure Truffle to connect to RSK networks

Open

truffle-config.js
file in your Truffle project and overwrite it with the following code:

const HDWalletProvider = require('@truffle/hdwallet-provider');
 
const fs = require('fs');
const mnemonic = fs.readFileSync(".secret").toString().trim();
if (!mnemonic || mnemonic.split(' ').length !== 12) {
  throw new Error('unable to retrieve mnemonic from .secret');
}
 
module.exports = {
  networks: {
  },
  compilers: {
    solc: {
    }
  }
}

The hdwallet-provider allows us to connect to any network by unlocking an account locally, including the RSK networks.

Also, we are loading the mnemonic stored in file .secret, and saving it at variable mnemonic.

Configure Truffle to connect to RSK regtest (local node)

In the truffle-config.js file, include this configuration at network section:

    development: {
      host: "127.0.0.1",
      port: 4444,
      network_id: "*"
    },

This is the result:

Get the current gas price of testnet

Get the current gas price of the testnet network, and save to .gas-price-testnet.json.

In your project folder, run this cURL command:

curl https://public-node.testnet.rsk.co/2.0.1/ -X POST -H "Content-Type: 
application/json" --data
'{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":1}' >
.gas-price-testnet.json

You should receive a response similar to the following in the file:

{"jsonrpc":"2.0","id":1,"result":"0x3938700"}

The result value is presented in hexadecimal.

Modify the truffle-config file again to use the updated gas price. After mnemonic part, include this:

const gasPriceTestnetRaw = 
fs.readFileSync(".gas-price-testnet.json").toString().trim();
const gasPriceTestnet = parseInt(JSON.parse(gasPriceTestnetRaw).result, 16);
if (typeof gasPriceTestnet !== 'number' || isNaN(gasPriceTestnet)) {
  throw new Error('unable to retrieve network gas price from
.gas-price-testnet.json');
}
console.log("Gas price Testnet: " + gasPriceTestnet);

Configure Truffle to connect to RSK testnet

In the truffle-config.js file, include this configuration at network section:

    testnet: {
      provider: () => new HDWalletProvider(mnemonic, 'https://public-node.testnet.rsk.co/2.0.1/'),
      network_id: 31,
      gasPrice: Math.floor(gasPriceTestnet * 1.1),
      networkCheckTimeout: 1e9
    },

Truffle config with local and testnet RSK networks

This is the final truffle-config.js file with configurations for both networks:

const HDWalletProvider = require('@truffle/hdwallet-provider');
 
const fs = require('fs');
const mnemonic = fs.readFileSync(".secret").toString().trim();
if (!mnemonic || mnemonic.split(' ').length !== 12) {
  throw new Error('unable to retrieve mnemonic from .secret');
}
 
const gasPriceTestnetRaw = fs.readFileSync(".gas-price-testnet.json").toString().trim();
const gasPriceTestnet = parseInt(JSON.parse(gasPriceTestnetRaw).result, 16);
if (typeof gasPriceTestnet !== 'number' || isNaN(gasPriceTestnet)) {
  throw new Error('unable to retrieve network gas price from .gas-price-testnet.json');
}
console.log("Gas price Testnet: " + gasPriceTestnet);
 
module.exports = {
networks: {
    development: {
      host: "127.0.0.1",
      port: 4444,
      network_id: "*"
    },
    testnet: {
      provider: () => new HDWalletProvider(mnemonic, 'https://public-node.testnet.rsk.co/2.0.1/'),
      network_id: 31,
      gasPrice: Math.floor(gasPriceTestnet * 1.1),
      networkCheckTimeout: 1e9
    },
  },
  compilers: {
    solc: {
    }
  }
}

Truffle Console connected to RSK network

Truffle has its own console to run commands and can be connected on any network previously configured in truffle-config.js file.

Connect to RSK regtest (local node)

Let’s open a Truffle console to connect to our local node.

In the terminal, inside the myproject folder, run this command:

truffle console

Any network defined with the name development is considered the default network.

Connect to RSK testnet

Thus far we have only connected to a blockchain that runs using just 1 node, that runs on your own computer. Let’s now switch to interacting with a “real” blockchain, which is running on multiple nodes distributed across multiple computers!

To connect Truffle console in another network, you need to specify the network:

In a new terminal, inside the myproject folder, run this command:

truffle console --network testnet

It takes a little longer to establish this connection when compared to the local node. This will open a new console.

Test the connection to RSK network

On any of the networks, run this commands in the Truffle console:

Block number

Shows the last block number.

(await web3.eth.getBlockNumber()).toString()

Network ID

To get the network ID, run this command:

(await web3.eth.net.getId()).toString()

For the local node, the network ID is 33.

And for testnet, it is 31.

Exit Truffle console

In the Truffle console, enter this command to exit the terminal:

.exit

Get addresses

We will use a special instruction in Truffle console to get the first 10 addresses in our hierarchical deterministic wallet for the RSK Testnet network, that are generated from our mnemonic.

In the terminal, inside the myproject folder, go to the Truffle console connected to testnet:

truffle console --network testnet

And run this command to save the addresses at variable accounts:

const accounts = Object.keys(web3.currentProvider.wallets)

See the addresses after it by entering the command below:

accounts

Now we will write them to a file named .accounts

await require('fs').promises.writeFile('.accounts', accounts.join('\n'))

Check balance

To check the balance of an account, for example, the first account of our list (account[0]), run this command in Truffle console:

(await web3.eth.getBalance(accounts[0])).toString()

The balance is 0 and we need some tR-BTC to pay gas fees, which will be used to publish smart contracts and interact with them. We shall obtain some in the next step.

TestNet Faucet

You can get some tR-BTC from the RSK Testnet faucet.

Copy the first address from .accounts file. In my case, it is

0xe16f6abdd5815f3d24b4e5c29138f863933b000a

Enter your wallet address and pass the CAPTCHA.

Wait a few seconds…

You can see my transaction hash:

0x4a2bf1f65c525219020c3a1215a29453c20f4ced90575d9a7d13f8fe666d05b4

Now I have 0.05 R-BTC!

Recheck balance

To check balance again, run this command in the Truffle console:

(await web3.eth.getBalance(accounts[0])).toString()

Great! Now I have 50000000000000000, which means that I have 0.05 tR-BTC with 18 decimal places of precision.

Where to go from here

At this point, we have installed all requirements and created an empty project using Truffle framework and Open Zeppelin smart contracts library, connected to both an RSK local node (Regtest) and the RSK Testnet.

We have not developed anything yet, but you are now ready to move on to the next tutorials, where we will develop some very cool projects!

Author: Solange Gueiros | Reviewers: Brendan Graetz and Owanate Amachree