How to build a DApp on Nebulas (Part 1)

This series will give a step-by-step explanation on how to start your journey of developing a DApp on the Nebulas blockchain. It assumes readers have already mastered the basics of Nebulas. If you haven’t, please visit our tutorials first.

You can also visit our FAQs if you have any questions, or get in touch with us directly at contact@nebulas.io.

Smart Contract Intro

Smart Contracts in Nebulas are similar to classes in OOP languages. These may contain persistent data in state variables as well as functions that can modify these variables.

Nebulas implements NVM as the contract execution engine. JavaScript is chosen as our first smart contract language.

The following is the simplest JS contract:

"use strict";
var BankVaultContract = function () {
// nothing
};
BankVaultContract.prototype = {
init: function() {
// nothing
}
};
module.exports = BankVaultContract;

In addition to JavaScript, we also support TypeScript. Here is the TS version of the above sample.

class BankVaultContract {
constructor() {
// nothing
}
    init() {
// nothing
}
}
module.exports = BankVaultContract;

As you can see, these empty contracts are meaningless but structurally correct. Keep these two key points in mind:

One. A contract must contain an init function, which will be executed only once when deployed. init can be passed for 0 or more arguments:

init: function(arg1, arg2, …) {
// do something with arg1, arg2, ...
}

Two. In Nebulas, we define two kinds of visibility for functions (JavaScript has no such visibility):

  • public All functions whose name matches regexp ^[a-zA-Z$][A-Za-z0-9_$]*$ are public, except init. Public functions can be called via transactions.
  • private All functions whose name starts with _ are private. A private function can only be called by public functions.

Deploy Contract

Each contract is uniquely identified with a Nebulas address (e.g. n1qsgj2C5zmYzS9TSkPTnp15bhCCocRPwno) as long as you send the contract (in JS or TS) to any Nebulas node.

// Request
curl -i -H 'Accept: application/json' -X POST http://localhost:8685/v1/admin/transaction -H 'Content-Type: application/json' -d '{"from":"n1NaY2ywi1J6ENA1htPa4FdeTRMo2hjpD8f","to":"n1NaY2ywi1J6ENA1htPa4FdeTRMo2hjpD8f","gasLimit":200000,"gasPrice":1000000,"value":"0","contract":{"source":"\"use strict\";\nvar BankVaultContract = function () {\n // nothing\n};\nBankVaultContract.prototype = {\n init: function() {\n // nothing\n }\n};\nmodule.exports = BankVaultContract;","sourceType":"js","args":""},"nonce":1}'

// Result
{
"result":
{ "txhash":"2dd7186d266c2139fcc92446b364ef1a1037bc96d571f7c8a1716bec44fe25d8","contract_address":"n1qsgj2C5zmYzS9TSkPTnp15bhCCocRPwno"
}
}

Wait for a moment, then check transaction receipt until the status changes to 1, which implies the contract has been successfully deployed.

> curl -i -H ‘Content-Type: application/json’ -X POST http://localhost:8685/v1/user/getTransactionReceipt -d ‘{“hash”:”2dd7186d266c2139fcc92446b364ef1a1037bc96d571f7c8a1716bec44fe25d8"}’
{"result":{"hash":"2dd7186d266c2139fcc92446b364ef1a1037bc96d571f7c8a1716bec44fe25d8",...,"status":1}}

Now anyone can access this contract with the contract_address.

What comes next in this series?

Libs, e.g., storage, event, etc. And how to call a contract function.