Walkthrough: build a Web3 App

End-to-end walkthrough — write a decentralized library smart contract, deploy it through TronIDE on the Nile testnet, and wire a TronLink-powered front-end against it.

📘

Prerequisites

This walkthrough takes a DApp from empty folder to running prototype. The example is a decentralized book-rental library: owners list books for daily rental, borrowers pay TRX for a rental period, and the contract tracks every rental on-chain.

You will:

  1. Review the library smart contract (Solidity)
  2. Deploy it to the Nile testnet via TronIDE
  3. Wire a Vue front-end against the deployed contract through TronLink

Preparations

Node.js v10+

# node -v
v10.24.1

TronLink

Install the TronLink Chrome extension and create or import an account. The DApp uses TronLink to inject TronWeb into the page and to sign transactions.


What you'll build

A decentralized library with three end-user actions:

  • Browse — list every available book
  • Add — list a new book for rental
  • Borrow — pay TRX to rent a book for a chosen period

Clone the full project:

git clone https://github.com/TRON-Developer-Hub/decentralized-library
cd decentralized-library
npm install

The repo contains both the Solidity contract and the Vue front-end. The walkthrough below explains how the pieces fit; refer back to the repo for full source.


Contract overview

The contract source lives in the repo above. This section summarises the on-chain shapes and entry points so the front-end code that follows makes sense — refer to the Solidity file directly for the full implementation, NatSpec comments, and modifier definitions.

Data shapes

Two structs hold the contract's state:

StructPurposeKey fields
BookA listed bookname, description, valid (false when on loan), price (TRX per day), owner
TrackingA single rental recordbookId, startTime, endTime, borrower

Each is keyed by an auto-incrementing ID:

uint256 public bookId;
uint256 public trackingId;

mapping(uint256 => Book) public books;
mapping(uint256 => Tracking) public trackings;

Public entry points

FunctionRoleEmits
addBook(name, description, price)List a new book; sets owner = msg.sender and valid = trueNewBook(bookId)
borrowBook(bookId, startTime, endTime) payablePay price × days, transfer TRX to the book's owner, record a Tracking entry, and flip valid to falseNewRental(bookId, trackingId)
deleteBook(bookId)Remove a book; restricted to the book's owner or the contract ownerDeleteBook(bookId)

Two helpers are kept internal so they can't be invoked directly through the ABI: _sendTRX (forwards TRX to the book's owner) and _createTracking (records the rental and flips valid).


Deploy and test

Many tools deploy Solidity contracts to TRON — TronBox (Truffle-style CLI), TronWeb programmatic deployment, Trident for JVM stacks, and others. This walkthrough uses TronIDE — a browser-based IDE that compiles and deploys without local toolchain setup — to keep the focus on the DApp wiring rather than the tooling.

Deploy to the Nile testnet first. Nile is one of TRON's public test networks — the right place to validate a contract before mainnet. See TRON networks for the full network comparison.

Get test TRX for Energy

Contract deployment burns or stakes TRX to pay for Energy. Claim test TRX from the Getting testnet tokens page — each address is eligible once per faucet.

Connect TronLink to TronIDE

A logged-in TronLink session is detected by TronIDE automatically. Confirm the active network in TronLink matches the network you want to deploy to (Nile, in this case):

Enable the required TronIDE modules

On first use, enable the Solidity Compiler and DEPLOYMENT modules from the TronIDE plugin manager:

Once enabled, the left sidebar shows both modules:

Compile

Create a new file Library.sol and paste the full contract from the repo:

Select compiler version 0.8.0+commit.7c2e641 from the Compiler dropdown and compile.

Deploy

Set the fee limit to 1000000000 (1,000 TRX in sun) — this caps the TRX you risk on Energy. For background on sizing fee_limit correctly, see FeeLimit & Energy cost.

Click Deploy. TronLink pops up to confirm and sign the deployment transaction:

Once mined, TronIDE renders the contract's callable methods in the panel below — quick sanity-check that the ABI loaded correctly:

Copy the deployed contract's address — the front-end will need it.


Build the DApp

Paste the deployed contract address into the libraryContractAddress variable in utils.js.

Integrate with TronLink

TronLink injects the TronWeb object into every page, giving the DApp a signing-capable connection to the TRON network. Wrap that into a contract handle the DApp can reuse.

Add the following to dapp-ui/plugins/utils.js — it fetches the contract object and stashes it in a module-level variable for downstream calls:

export async function setLibraryContract() {
    bookRentContract = await
        window.tronWeb.contract().at(libraryContractAddress);
}

Initialise the handle when the page mounts (index.vue), then load the book list:

async mounted() {
    // init contract object
    await setLibraryContract();
    // fetch all books
    const books = await fetchAllBooks();
    this.posts = books;
}

The library exposes three user actions, each wired to one of the contract's public entry points.

Add a book

The Add-a-book form (bookForm.vue) collects title, description, and per-day price. On submit, convert TRX to sun and forward to the contract:

postAd() {
    // convert price from TRX to SUN
    postBookInfo(this.title, this.description, tronWeb.toSun(this.price));
}

postBookInfo() in dapp-ui/plugins/utils.js calls the contract's addBook:

const result = await bookRentContract.addBook(name, description, price).send({
    feeLimit: 100_000_000,
    callValue: 0,
    shouldPollResponse: true
});

Browse available books

fetchAllBooks() iterates bookId from 0 to the current counter and reads each entry. Deleted books leave behind empty slots — skip those by filtering on book.name:

const books = [];

const bookId = await bookRentContract.bookId().call();
// iterate from 0 till bookId
for (let i = 0; i < bookId; i++) {
    const book = await bookRentContract.books(i).call();
    if (book.name != "") {       // filter the deleted books
        books.push({
            id: i,
            name: book.name,
            description: book.description,
            price: tronWeb.fromSun(book.price)
        });
    }
}
return books;

Call fetchAllBooks() from index.vue to render the list on the homepage.

Borrow a book

The detail modal (detailsModal.vue) collects the borrower's chosen rental period. Compute the total cost client-side, then call the contract:

// get Start date
const startDay = this.getDayOfYear(this.startDate);
// get End date
const endDay = this.getDayOfYear(this.endDate);
// price calculation
const totalPrice = tronWeb.toSun(this.propData.price) * (endDay - startDay);
// call contract
borrowBook(this.propData.id, startDay, endDay, totalPrice);

borrowBook() in dapp-ui/plugins/utils.js sends the rental payment as callValue:

const result = await bookRentContract.borrowBook(spaceId, checkInDate, checkOutDate).send({
    feeLimit: 100_000_000,
    callValue: totalPrice,
    shouldPollResponse: true
});

That's the full DApp.


Run the DApp

With TronLink logged in, start the dev server:

npm run dev

Open http://localhost:3000 in the browser:

Click Rent Your Books in the top-right corner to open the add-book form. Fill in title, description, and per-day price:

Submit. The DApp calls the contract's addBook, TronLink intercepts the transaction, and prompts for signature:

Once the transaction lands on-chain, the new book appears in the listing:

Click View on any book to inspect details and pick a rental period. Lent Now triggers borrowBook — TronLink prompts for one more signature to broadcast the rental:


Related resources