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:
- Review the library smart contract (Solidity)
- Deploy it to the Nile testnet via TronIDE
- Wire a Vue front-end against the deployed contract through TronLink
Preparations
Node.js v10+
# node -v
v10.24.1TronLink
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 installThe 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:
| Struct | Purpose | Key fields |
|---|---|---|
Book | A listed book | name, description, valid (false when on loan), price (TRX per day), owner |
Tracking | A single rental record | bookId, 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
| Function | Role | Emits |
|---|---|---|
addBook(name, description, price) | List a new book; sets owner = msg.sender and valid = true | NewBook(bookId) |
borrowBook(bookId, startTime, endTime) payable | Pay price × days, transfer TRX to the book's owner, record a Tracking entry, and flip valid to false | NewRental(bookId, trackingId) |
deleteBook(bookId) | Remove a book; restricted to the book's owner or the contract owner | DeleteBook(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 devOpen 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
- Listen to Contract Events — subscribe to the
NewBook,NewRental, andDeleteBookevents emitted by this contract - Send Your First Transaction — a simpler starting point if this walkthrough is too dense
- TRC-20 Issuing — issue a token from a contract you control
- TronLink integration — TronLink-specific provider events, multi-account handling, and disconnect flows
- FeeLimit & Energy cost — set
fee_limitcorrectly so deployments and contract calls don't run out of Energy
Updated 14 days ago