TronWeb.js is the official JavaScript SDK for interacting with the TRON blockchain. Whether you're building decentralized applications, integrating TRON payments, or creating automated trading bots, TronWeb.js provides all the tools you need. This comprehensive guide takes you from installation to production deployment.
What Is TronWeb.js?
TronWeb.js is the official JavaScript library that provides a complete interface for interacting with the TRON network. Similar to Web3.js for Ethereum, TronWeb.js abstracts the complexity of blockchain interactions into simple, intuitive methods that JavaScript developers can easily understand and implement.
Developed and maintained by the TRON DAO, TronWeb.js is the foundation for thousands of DApps running on the TRON network. It handles everything from basic TRX transfers to complex smart contract interactions, making it the essential toolkit for any TRON developer.
Core Features and Capabilities
TronWeb.js offers a comprehensive feature set:
- Wallet Management: Create, import, and manage TRON wallets with full HD wallet support
- Transaction Building: Construct and broadcast all transaction types including TRX, TRC-10, and TRC-20
- Smart Contract Interaction: Deploy, call, and query smart contracts with ABI encoding/decoding
- Event System: Subscribe to blockchain events and contract emissions in real-time
- Resource Management: Query and manage Energy and Bandwidth resources
- TronGrid Integration: Built-in support for TronGrid's enhanced API services
- Utilities: Address conversion, hex encoding, and cryptographic functions
Setting Up Your Development Environment
Before diving into TronWeb.js, ensure you have a proper development environment. You'll need Node.js (version 14 or higher recommended) and a code editor with JavaScript support.
Installation and Configuration
Install TronWeb.js via npm or yarn:
# Using npm
npm install tronweb
# Using yarn
yarn add tronweb
# Using pnpm
pnpm add tronweb
For browser-based projects, you can also use the CDN version, though npm installation is recommended for production applications to ensure version consistency.
Initializing TronWeb
Create a TronWeb instance with your configuration:
const TronWeb = require('tronweb');
// For mainnet
const tronWeb = new TronWeb({
fullHost: 'https://api.trongrid.io',
headers: { 'TRON-PRO-API-KEY': 'your-api-key' },
privateKey: 'your-private-key' // Optional
});
// For Nile testnet (development)
const tronWebTestnet = new TronWeb({
fullHost: 'https://nile.trongrid.io',
privateKey: 'your-testnet-private-key'
});
// For Shasta testnet
const tronWebShasta = new TronWeb({
fullHost: 'https://api.shasta.trongrid.io',
privateKey: 'your-shasta-private-key'
});
Get your free API key from TronGrid to access higher rate limits and premium features. For testing, the Nile testnet is recommended as it most closely mirrors mainnet behavior.
Working with Wallets and Accounts
Wallet management is fundamental to any blockchain application. TronWeb.js provides comprehensive tools for creating, importing, and managing TRON accounts.
Creating New Wallets
Generate a new TRON wallet with a single function call:
// Generate a new random account
const newAccount = await tronWeb.createAccount();
console.log('Address:', newAccount.address.base58);
console.log('Hex Address:', newAccount.address.hex);
console.log('Private Key:', newAccount.privateKey);
console.log('Public Key:', newAccount.publicKey);
// IMPORTANT: Store the private key securely!
// Never expose it in client-side code or logs in production
The generated account includes both Base58 (T-prefixed) and hex format addresses. Always store private keys securely using environment variables or a secrets manager in production environments.
Importing Existing Wallets
Import an existing wallet using its private key:
// Set the default address for transactions
tronWeb.setPrivateKey('your-private-key');
// Or create a new instance with the private key
const tronWebWithKey = new TronWeb({
fullHost: 'https://api.trongrid.io',
privateKey: 'your-private-key'
});
// Get address from private key
const address = tronWeb.address.fromPrivateKey('your-private-key');
console.log('Wallet Address:', address);
Managing Multiple Accounts
For applications requiring multiple wallets:
class WalletManager {
constructor(tronWeb) {
this.tronWeb = tronWeb;
this.accounts = new Map();
}
addAccount(name, privateKey) {
const address = this.tronWeb.address.fromPrivateKey(privateKey);
this.accounts.set(name, { privateKey, address });
return address;
}
async getBalance(name) {
const account = this.accounts.get(name);
if (!account) throw new Error('Account not found');
const balance = await this.tronWeb.trx.getBalance(account.address);
return this.tronWeb.fromSun(balance); // Convert from Sun to TRX
}
setActiveAccount(name) {
const account = this.accounts.get(name);
if (!account) throw new Error('Account not found');
this.tronWeb.setPrivateKey(account.privateKey);
}
}
Building and Sending Transactions
Transaction handling is at the core of any blockchain application. TronWeb.js provides intuitive methods for building, signing, and broadcasting various transaction types.
TRX Transfers
Send TRX to another address:
async function sendTRX(toAddress, amount) {
try {
// Amount in TRX (will be converted to Sun internally)
const amountInSun = tronWeb.toSun(amount);
// Build the transaction
const transaction = await tronWeb.transactionBuilder.sendTrx(
toAddress,
amountInSun,
tronWeb.defaultAddress.base58
);
// Sign the transaction
const signedTx = await tronWeb.trx.sign(transaction);
// Broadcast to the network
const result = await tronWeb.trx.sendRawTransaction(signedTx);
console.log('Transaction ID:', result.txid);
return result;
} catch (error) {
console.error('Transfer failed:', error.message);
throw error;
}
}
// Send 10 TRX
await sendTRX('TRecipientAddress...', 10);
TRC-20 Token Transfers
Transfer TRC-20 tokens like USDT:
async function sendTRC20(contractAddress, toAddress, amount, decimals = 6) {
try {
// Get contract instance
const contract = await tronWeb.contract().at(contractAddress);
// Calculate amount with decimals
const adjustedAmount = amount * Math.pow(10, decimals);
// Call the transfer function
const result = await contract.methods.transfer(toAddress, adjustedAmount).send({
feeLimit: 100000000, // 100 TRX fee limit
callValue: 0
});
console.log('Transaction ID:', result);
return result;
} catch (error) {
console.error('TRC-20 transfer failed:', error.message);
throw error;
}
}
// USDT on TRON contract address
const USDT_CONTRACT = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t';
// Send 100 USDT
await sendTRC20(USDT_CONTRACT, 'TRecipientAddress...', 100, 6);
For TRC-20 transfers, ensure your account has sufficient Energy to cover the smart contract execution. You can check Energy costs on TRONSCAN.
Transaction Monitoring
Track transaction status and get detailed information:
async function getTransactionDetails(txId) {
// Get transaction info
const txInfo = await tronWeb.trx.getTransaction(txId);
// Get transaction receipt with execution results
const txReceipt = await tronWeb.trx.getTransactionInfo(txId);
return {
id: txInfo.txID,
blockNumber: txReceipt.blockNumber,
timestamp: txReceipt.blockTimeStamp,
status: txReceipt.receipt?.result || 'PENDING',
energyUsed: txReceipt.receipt?.energy_usage_total || 0,
bandwidthUsed: txReceipt.receipt?.net_usage || 0,
fee: tronWeb.fromSun(txReceipt.fee || 0)
};
}
// Poll for confirmation
async function waitForConfirmation(txId, maxAttempts = 20) {
for (let i = 0; i < maxAttempts; i++) {
const info = await tronWeb.trx.getTransactionInfo(txId);
if (info.id) {
return info;
}
await new Promise(resolve => setTimeout(resolve, 3000));
}
throw new Error('Transaction not confirmed within timeout');
}
Smart Contract Interaction
TronWeb.js provides powerful tools for interacting with smart contracts, from simple queries to complex deployments. The SDK handles ABI encoding and decoding automatically.
Reading Contract Data
Query smart contract state without spending resources:
async function getTokenInfo(contractAddress) {
const contract = await tronWeb.contract().at(contractAddress);
// Read multiple contract properties
const [name, symbol, decimals, totalSupply] = await Promise.all([
contract.methods.name().call(),
contract.methods.symbol().call(),
contract.methods.decimals().call(),
contract.methods.totalSupply().call()
]);
return {
name,
symbol,
decimals: decimals.toNumber(),
totalSupply: totalSupply.toString()
};
}
async function getTokenBalance(contractAddress, walletAddress) {
const contract = await tronWeb.contract().at(contractAddress);
const balance = await contract.methods.balanceOf(walletAddress).call();
return balance.toString();
}
Writing to Contracts
Execute state-changing contract functions:
async function approveSpender(tokenContract, spenderAddress, amount) {
const contract = await tronWeb.contract().at(tokenContract);
const result = await contract.methods.approve(
spenderAddress,
amount
).send({
feeLimit: 50000000, // 50 TRX
callValue: 0
});
return result;
}
async function stakeTokens(stakingContract, amount) {
const contract = await tronWeb.contract().at(stakingContract);
const result = await contract.methods.stake(amount).send({
feeLimit: 100000000,
callValue: 0,
shouldPollResponse: true // Wait for confirmation
});
return result;
}
Deploying Contracts
Deploy new smart contracts to the TRON network:
async function deployContract(abi, bytecode, constructorParams = []) {
try {
const contract = await tronWeb.contract().new({
abi: abi,
bytecode: bytecode,
feeLimit: 1000000000, // 1000 TRX for deployment
callValue: 0,
parameters: constructorParams
});
console.log('Contract deployed at:', contract.address);
return contract;
} catch (error) {
console.error('Deployment failed:', error.message);
throw error;
}
}
// Example: Deploy a simple token
const tokenABI = [...]; // Your contract ABI
const tokenBytecode = '0x...'; // Compiled bytecode
const deployedToken = await deployContract(
tokenABI,
tokenBytecode,
['MyToken', 'MTK', 18, '1000000000000000000000000']
);
For complex contracts, consider using TronIDE for compilation and testing before programmatic deployment. You can also use www.createtrontoken.com for no-code token deployment.
Event Listening and Webhooks
Real-time event monitoring is crucial for building responsive DApps. TronWeb.js supports both polling and WebSocket-based event listening.
Subscribing to Contract Events
async function watchTransferEvents(contractAddress) {
const contract = await tronWeb.contract().at(contractAddress);
// Watch for Transfer events
contract.Transfer().watch((err, event) => {
if (err) {
console.error('Event error:', err);
return;
}
console.log('Transfer detected:', {
from: tronWeb.address.fromHex(event.result.from),
to: tronWeb.address.fromHex(event.result.to),
value: event.result.value.toString(),
txId: event.transaction
});
});
}
// Get historical events
async function getHistoricalEvents(contractAddress, eventName, since) {
const events = await tronWeb.getEventResult(contractAddress, {
eventName: eventName,
sinceTimestamp: since,
sort: 'block_timestamp',
size: 200
});
return events;
}
Building Real-Time Applications
class EventMonitor {
constructor(tronWeb, contractAddress) {
this.tronWeb = tronWeb;
this.contractAddress = contractAddress;
this.handlers = new Map();
}
on(eventName, handler) {
if (!this.handlers.has(eventName)) {
this.handlers.set(eventName, []);
}
this.handlers.get(eventName).push(handler);
}
async start() {
const contract = await this.tronWeb.contract().at(this.contractAddress);
// Subscribe to all events
for (const [eventName, handlers] of this.handlers) {
contract[eventName]().watch((err, event) => {
if (err) return;
handlers.forEach(handler => handler(event));
});
}
}
}
// Usage
const monitor = new EventMonitor(tronWeb, USDT_CONTRACT);
monitor.on('Transfer', (event) => {
console.log('USDT Transfer:', event);
});
monitor.on('Approval', (event) => {
console.log('USDT Approval:', event);
});
await monitor.start();
TronGrid API Integration
TronGrid provides enhanced API services beyond basic node functionality. TronWeb.js integrates seamlessly with TronGrid for advanced queries.
Account and Transaction Queries
// Get complete account information
async function getAccountDetails(address) {
const account = await tronWeb.trx.getAccount(address);
const accountResources = await tronWeb.trx.getAccountResources(address);
return {
address: address,
balance: tronWeb.fromSun(account.balance || 0),
bandwidth: {
free: accountResources.freeNetLimit || 0,
used: accountResources.freeNetUsed || 0,
staked: accountResources.NetLimit || 0
},
energy: {
available: accountResources.EnergyLimit || 0,
used: accountResources.EnergyUsed || 0
},
frozenBalance: account.frozen || [],
votes: account.votes || []
};
}
// Get transaction history using TronGrid
async function getTransactionHistory(address, limit = 50) {
const transactions = await tronWeb.trx.getTransactionsRelated(
address,
'all', // 'from', 'to', or 'all'
limit
);
return transactions.data || [];
}
Rate Limits and API Keys
Configure TronGrid API keys for higher rate limits:
// Production configuration with API key
const tronWeb = new TronWeb({
fullHost: 'https://api.trongrid.io',
headers: {
'TRON-PRO-API-KEY': process.env.TRONGRID_API_KEY
},
privateKey: process.env.PRIVATE_KEY
});
// Rate limit handling
class RateLimitedTronWeb {
constructor(tronWeb, requestsPerSecond = 10) {
this.tronWeb = tronWeb;
this.queue = [];
this.interval = 1000 / requestsPerSecond;
this.lastRequest = 0;
}
async execute(fn) {
const now = Date.now();
const waitTime = Math.max(0, this.lastRequest + this.interval - now);
await new Promise(resolve => setTimeout(resolve, waitTime));
this.lastRequest = Date.now();
return fn();
}
}
Resource Management with TronWeb
Understanding and managing Energy and Bandwidth is essential for cost-effective TRON development. TronWeb.js provides methods to query and manage these resources.
Energy and Bandwidth Queries
async function getResourceStatus(address) {
const resources = await tronWeb.trx.getAccountResources(address);
return {
bandwidth: {
free: resources.freeNetLimit || 1500,
freeUsed: resources.freeNetUsed || 0,
staked: resources.NetLimit || 0,
stakedUsed: resources.NetUsed || 0
},
energy: {
total: resources.EnergyLimit || 0,
used: resources.EnergyUsed || 0,
available: (resources.EnergyLimit || 0) - (resources.EnergyUsed || 0)
}
};
}
// Estimate Energy for contract call
async function estimateEnergy(contractAddress, functionSelector, parameters) {
try {
const result = await tronWeb.transactionBuilder.triggerConstantContract(
contractAddress,
functionSelector,
{},
parameters
);
return result.energy_used || 0;
} catch (error) {
console.error('Energy estimation failed:', error);
return null;
}
}
Staking Operations
Manage TRX staking for resources (Stake 2.0):
// Freeze TRX for Energy (Stake 2.0)
async function freezeForEnergy(amount) {
const amountInSun = tronWeb.toSun(amount);
const transaction = await tronWeb.transactionBuilder.freezeBalanceV2(
amountInSun,
'ENERGY',
tronWeb.defaultAddress.base58
);
const signedTx = await tronWeb.trx.sign(transaction);
return await tronWeb.trx.sendRawTransaction(signedTx);
}
// Freeze TRX for Bandwidth
async function freezeForBandwidth(amount) {
const amountInSun = tronWeb.toSun(amount);
const transaction = await tronWeb.transactionBuilder.freezeBalanceV2(
amountInSun,
'BANDWIDTH',
tronWeb.defaultAddress.base58
);
const signedTx = await tronWeb.trx.sign(transaction);
return await tronWeb.trx.sendRawTransaction(signedTx);
}
// Unfreeze TRX
async function unfreezeBalance(amount, resource) {
const amountInSun = tronWeb.toSun(amount);
const transaction = await tronWeb.transactionBuilder.unfreezeBalanceV2(
amountInSun,
resource, // 'ENERGY' or 'BANDWIDTH'
tronWeb.defaultAddress.base58
);
const signedTx = await tronWeb.trx.sign(transaction);
return await tronWeb.trx.sendRawTransaction(signedTx);
}
Error Handling and Best Practices
Robust error handling is critical for production applications. TronWeb.js throws specific errors that you can catch and handle appropriately.
Common Error Patterns
class TronError extends Error {
constructor(message, code, details) {
super(message);
this.code = code;
this.details = details;
}
}
async function safeTrxTransfer(to, amount) {
try {
// Validate address
if (!tronWeb.isAddress(to)) {
throw new TronError('Invalid address', 'INVALID_ADDRESS', { to });
}
// Check balance
const balance = await tronWeb.trx.getBalance();
const amountSun = tronWeb.toSun(amount);
if (balance < amountSun) {
throw new TronError(
'Insufficient balance',
'INSUFFICIENT_FUNDS',
{ balance: tronWeb.fromSun(balance), required: amount }
);
}
// Execute transfer
const tx = await tronWeb.transactionBuilder.sendTrx(to, amountSun);
const signedTx = await tronWeb.trx.sign(tx);
const result = await tronWeb.trx.sendRawTransaction(signedTx);
if (!result.result) {
throw new TronError(
'Transaction rejected',
'TX_REJECTED',
result
);
}
return result;
} catch (error) {
if (error instanceof TronError) throw error;
// Handle TronWeb-specific errors
if (error.message?.includes('bandwidth')) {
throw new TronError('Insufficient bandwidth', 'NO_BANDWIDTH', error);
}
if (error.message?.includes('energy')) {
throw new TronError('Insufficient energy', 'NO_ENERGY', error);
}
throw new TronError('Transfer failed', 'UNKNOWN', error);
}
}
Retry Strategies
async function withRetry(fn, maxAttempts = 3, delay = 1000) {
let lastError;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error;
// Don't retry certain errors
if (error.code === 'INVALID_ADDRESS' ||
error.code === 'INSUFFICIENT_FUNDS') {
throw error;
}
if (attempt < maxAttempts) {
const backoff = delay * Math.pow(2, attempt - 1);
console.log(`Attempt ${attempt} failed, retrying in ${backoff}ms...`);
await new Promise(resolve => setTimeout(resolve, backoff));
}
}
}
throw lastError;
}
// Usage
const result = await withRetry(
() => sendTRX('TAddress...', 10),
3,
2000
);
Production Deployment Strategies
Moving from development to production requires careful consideration of security, performance, and reliability.
Security Considerations
// NEVER hardcode private keys
// Use environment variables or secrets managers
// Good: Environment variables
const tronWeb = new TronWeb({
fullHost: process.env.TRON_FULL_HOST,
headers: { 'TRON-PRO-API-KEY': process.env.TRONGRID_API_KEY },
privateKey: process.env.TRON_PRIVATE_KEY
});
// Better: Use a secrets manager (AWS Secrets Manager example)
const { SecretsManagerClient, GetSecretValueCommand } = require('@aws-sdk/client-secrets-manager');
async function getPrivateKey() {
const client = new SecretsManagerClient({ region: 'us-east-1' });
const response = await client.send(
new GetSecretValueCommand({ SecretId: 'tron/private-key' })
);
return JSON.parse(response.SecretString).privateKey;
}
// For web applications: Use TronLink
if (typeof window !== 'undefined' && window.tronWeb) {
// User's TronLink wallet handles private keys
const tronWeb = window.tronWeb;
}
// Connection pooling for high-throughput applications
class TronWebPool {
constructor(config, poolSize = 5) {
this.instances = [];
for (let i = 0; i < poolSize; i++) {
this.instances.push(new TronWeb(config));
}
this.currentIndex = 0;
}
getInstance() {
const instance = this.instances[this.currentIndex];
this.currentIndex = (this.currentIndex + 1) % this.instances.length;
return instance;
}
}
// Caching for frequently accessed data
const NodeCache = require('node-cache');
const cache = new NodeCache({ stdTTL: 60 }); // 60 second cache
async function getCachedBalance(address) {
const cacheKey = `balance:${address}`;
let balance = cache.get(cacheKey);
if (balance === undefined) {
balance = await tronWeb.trx.getBalance(address);
cache.set(cacheKey, balance);
}
return balance;
}
Building a Complete DApp Example
Let's put it all together with a complete example of a token dashboard:
const TronWeb = require('tronweb');
class TokenDashboard {
constructor(apiKey) {
this.tronWeb = new TronWeb({
fullHost: 'https://api.trongrid.io',
headers: { 'TRON-PRO-API-KEY': apiKey }
});
this.USDT_CONTRACT = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t';
}
async getWalletOverview(address) {
const [trxBalance, usdtBalance, resources] = await Promise.all([
this.tronWeb.trx.getBalance(address),
this.getTokenBalance(this.USDT_CONTRACT, address),
this.tronWeb.trx.getAccountResources(address)
]);
return {
address,
trx: this.tronWeb.fromSun(trxBalance),
usdt: usdtBalance / 1e6, // USDT has 6 decimals
energy: resources.EnergyLimit - (resources.EnergyUsed || 0),
bandwidth: (resources.freeNetLimit || 1500) - (resources.freeNetUsed || 0)
};
}
async getTokenBalance(contractAddress, walletAddress) {
const contract = await this.tronWeb.contract().at(contractAddress);
const balance = await contract.methods.balanceOf(walletAddress).call();
return balance.toNumber();
}
async getRecentTransactions(address, limit = 10) {
const txs = await this.tronWeb.trx.getTransactionsRelated(address, 'all', limit);
return (txs.data || []).map(tx => ({
id: tx.txID,
type: tx.raw_data?.contract?.[0]?.type,
timestamp: tx.raw_data?.timestamp,
success: tx.ret?.[0]?.contractRet === 'SUCCESS'
}));
}
}
// Usage
const dashboard = new TokenDashboard(process.env.TRONGRID_API_KEY);
const overview = await dashboard.getWalletOverview('TYourAddress...');
console.log(overview);
Conclusion and Next Steps
TronWeb.js is a powerful and comprehensive SDK that enables developers to build sophisticated applications on the TRON blockchain. From basic wallet operations to complex smart contract interactions, the library provides all the tools needed for production-ready DApps.
Key takeaways from this guide:
- TronWeb.js provides intuitive methods for all TRON blockchain interactions
- Proper error handling and retry strategies are essential for production applications
- Resource management (Energy and Bandwidth) should be integrated into your application logic
- Security best practices, especially around private key management, are non-negotiable
- TronGrid API keys unlock higher rate limits and better reliability
For further learning, explore the official TRON Developer Documentation, experiment with Nile Testnet, and join the TRON Discord community for support and collaboration.