Scortik Platform

Beginner

How to create a Dapp On Tron Network

In this tutorial, we will be learning how to create a decentralized application (DApp) on the Tron network. We will be building a decentralized library that allows users to borrow, browse, and add books. We will be using TronLink’s Chrome extension and Node.js for this tutorial. We will be defining the data structure for our DApp and implementing functions such as adding a book, borrowing a book, and deleting a book from the library. We will also be defining events for our DApp to track new rentals and deleted books. Finally, we will be deploying our DApp on the Tron network and testing its functionality.

Install

Nodej v10+

Shell

# node -v
v10.24.1

What Are We Doing

We are building a decentralized library that contains the following functions:

  • Book borrowing

  • Book browsing

  • Book adding

Download the complete project code from here, and run npm install to install dependencies.

Data Structure

Typically, borrowers are concerned with the title, content, availability, and price of the book. On this basis, we design a structure in the contract called Book, which comprises the following properties:

solidity

struct Book {
       string name;
       string description;
       bool valid;      // false if been borrowed
       uint256 price;   // TRX per day
       address owner;   // owner of the book
}

We hope that the library will be able to have an easy way to find every book. To do this, we build a bookId attribute and a mapping relationship between bookId and Book, named books.

solidity

uint256 public bookId;

mapping (uint256 => Book) public books;

Additionally, we must keep track of each book’s rental information, including the borrower and the start and end dates.

As with Book, construct a structure called Tracking to keep track of this data. This structure possesses the following fields:

solidity

struct Tracking {
       uint256 bookId;
       uint256 startTime; // start time, in timestamp
       uint256 endTime; // end time, in timestamp
       address borrower; // borrower's address
}

Similarly, a mapping relationship must be established to manage each rental record:

solidity

uint256 public trackingId;

mapping(uint256 => Tracking) public trackings;

Functions and Events

We are adding fundamental functions to our library, including:

  • Add a book to the library – addBook
  • Borrow a book – borrowBook
  • Remove a book from the library – deleteBook
addBook

solidity

/**
* @dev Add a Book with predefined `name`, `description` and `price`
* to the library.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {NewBook} event.
*/
function addBook(string memory name, string memory description, uint256 price) public returns (bool) {
       Book memory book = Book(name, description, true, price, _msgSender());

       books[bookId] = book;

       emit NewBook(bookId++);

       return true;
}

/**
* @dev Emitted when a new book is added to the library.
* Note bookId starts from 0.
*/
event NewBook(uint256 bookId);
borrowBook

solidity

/**
* @dev Borrow a book has `_bookId`. The rental period starts from
* `startTime` ends with `endTime`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a `NewRental` event.
*/
function borrowBook(uint256 _bookId, uint256 startTime, uint256 endTime) public payable returns(bool) {
       Book storage book = books[_bookId];

       require(book.valid == true, "The book is currently on loan");

       require(_msgValue() == book.price * _days(startTime, endTime), "Incorrect fund sent.");

       _sendTRX(book.owner, _msgValue());

       _createTracking(_bookId, startTime, endTime);

       emit NewRental(_bookId, trackingId++);
}
deleteBook

solidity

/**
* @dev Delete a book from the library. Only the book's owner or the
* library's owner is authorised for this operation.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a `DeleteBook` event.
*/
function deleteBook(uint256 _bookId) public returns(bool) {
       require(_msgSender() == books[_bookId].owner || isOwner(),
               "You are not authorised to delete this book.");
      
       delete books[_bookId];

       emit DeleteBook(_bookId);

       return true;
}

We use two tool methods in the borrowBook method: _sendTRX and _createTracking. We do not wish for users to invoke these APIs. As a result, in accordance with Solidity’s standards, we identify them as internal, which means they can be accessed only within the contract. 

_sendTRX

solidity

/**
* @dev Send TRX to the book's owner.
*/
function _sendTRX(address receiver, uint256 value) internal {
       payable(address(uint160(receiver))).transfer(value);
}
_createTracking

solidity

/**
* @dev Create a new rental tracking.
*/
function _createTracking(uint256 _bookId, uint256 startTime, uint256 endTime) internal {
         trackings[trackingId] = Tracking(_bookId, startTime, endTime, _msgSender());

         Book storage book = books[_bookId];

         book.valid = false;
 }

The contract is done, it’s time to deploy it.