TronDEX — Documentation
A complete decentralized exchange for the TRON blockchain: smart contracts, a modern Next.js web app, and one-command deployment. Thank you for your purchase.
Version 1.0.0 · Updated September 2026 · Live demo tron-exchange.blockshark.com
Overview
TronDEX is a fully functional decentralized exchange (DEX) built on the TRON blockchain. It implements the Uniswap V2 AMM (Automated Market Maker) model, adapted for the TRON Virtual Machine (TVM). Users can swap TRC-20 tokens, provide liquidity to earn fees, and stake LP tokens in yield farms.
Token Swapping
Instant token-to-token trades powered by the constant-product AMM formula (x × y = k) with 0.3% swap fee.
Liquidity Pools
Provide liquidity to token pairs and earn a share of trading fees proportional to your pool share.
Yield Farming
Stake LP tokens in farms to earn TDEX governance token rewards, with configurable APR per pool.
Portfolio Dashboard
Track token holdings, liquidity positions, farming rewards, and full transaction history in one place.
Tech Stack
Frontend
| Technology | Version | Purpose |
|---|---|---|
| Next.js | 16.x | React framework with App Router, SSR, Turbopack |
| React | 19.x | UI library |
| TypeScript | 5.x | Type-safe JavaScript |
| Tailwind CSS | 4.x | Utility-first CSS styling |
| shadcn/ui | Latest | Accessible component library (Radix UI based) |
| Zustand | 5.x | Lightweight state management |
| TanStack Query | 5.x | Async data fetching with caching |
| TronWeb | 6.x | TRON blockchain SDK |
| @tronweb3 Adapters | Latest | TronLink + WalletConnect integration |
| BigNumber.js | 9.x | Arbitrary-precision arithmetic |
| Lucide React | Latest | Icon library |
| Sonner | 2.x | Toast notifications |
| next-themes | 0.4.x | Dark/light theme support |
Smart Contracts
| Technology | Version | Purpose |
|---|---|---|
| Solidity | 0.8.20 | Smart contract language |
| TronBox | Latest | Compile and migrate contracts |
| EVM Version | Paris | TVM-compatible EVM target (avoids PUSH0 opcode) |
Testing
| Technology | Purpose |
|---|---|
| Vitest | Unit test runner |
| @testing-library/react | React component testing |
Requirements
System Requirements
- Node.js — v18.17 or later (v20+ recommended)
- npm — v9 or later (comes with Node.js)
- TronBox — For contract compilation (install globally:
npm install -g tronbox)
For Development & Testing
- TronLink Wallet — Browser extension for TRON (Chrome/Edge/Firefox)
- Nile Testnet TRX — Get free test TRX from nileex.io faucet
- WalletConnect Project ID — Optional, for WalletConnect support. Get from cloud.walletconnect.com
For Mainnet Deployment
- TRX — For contract deployment energy costs (~5,000-8,000 TRX total)
- Private key — Deployer wallet with sufficient TRX balance
- TronGrid API key — Optional but recommended for production. Get from trongrid.io
Installation
Extract the zip file
Extract the zip archive to your desired project directory.
Install dependencies
npm install
Set up environment variables
Copy the example file and fill in your values:
cp .env.example .env.local
Then edit .env.local with your configuration (see Environment Variables).
Start the development server
npm run dev
Open http://localhost:3000 in your browser. The app will hot-reload as you make changes.
Run tests (optional)
npm test # Run all tests once
npm run test:watch # Watch mode
npm run test:coverage # With coverage report
Available Scripts
| Command | Description |
|---|---|
npm run dev | Start development server with hot reload (Turbopack) |
npm run build | Create optimized production build |
npm start | Start production server (requires build first) |
npm run lint | Run ESLint code linting |
npm test | Run unit tests with Vitest |
npm run test:watch | Run tests in watch mode |
npm run test:coverage | Generate test coverage report |
Project Structure
Environment Variables
Create a .env.local file in the project root with these values:
# WalletConnect Project ID (get from cloud.walletconnect.com)
NEXT_PUBLIC_WC_PROJECT_ID=your-walletconnect-project-id
# Default network: "mainnet", "nile", or "shasta"
NEXT_PUBLIC_DEFAULT_NETWORK=nile
# Optional: TronGrid API key for higher rate limits
NEXT_PUBLIC_TRONGRID_API_KEY=your-api-key
# These are optional overrides (addresses are in src/config/contracts.ts)
NEXT_PUBLIC_FACTORY_ADDRESS=
NEXT_PUBLIC_ROUTER_ADDRESS=
NEXT_PUBLIC_TSWAP_TOKEN_ADDRESS=
NEXT_PUBLIC_FARM_ADDRESS=
NEXT_PUBLIC_ prefix is required for variables used in the browser. Without it, the variable will only be available on the server.
Network Configuration
Networks are configured in src/config/networks.ts:
| Network | RPC Endpoint | Chain ID | Explorer |
|---|---|---|---|
| Mainnet | https://api.trongrid.io |
0x2b6653dc |
tronscan.org |
| Nile | https://nile.trongrid.io |
0xcd8690dc |
nile.tronscan.org |
| Shasta | https://api.shasta.trongrid.io |
0x94a9059e |
shasta.tronscan.org |
To change the default network, edit NEXT_PUBLIC_DEFAULT_NETWORK in your .env.local file or update the DEFAULT_NETWORK export in src/config/networks.ts.
Contract Addresses
All deployed contract addresses are stored in src/config/contracts.ts. Update this file after deploying to a new network.
Current Nile Testnet Addresses
The bundled deployment is live and verifiable on Nile TronScan.
| Contract | Address |
|---|---|
| Factory | TVJa842vDvEcUzj3wRr15Jv5o5PjMxLiNG |
| Router | TChGFBkSW67erU2zj9ERdpWpkYvKwMqAEw |
| WTRX | TBaySNgxi2xL9Ccgb36UGfhceRreDNz89j |
| TDEX Token | TZ8DDibhAHk8mAWPhZ6HQk4PaynWMnQwR7 |
| Farm | TLdxd12dFjzvkHxBTit3zMnUtSjUBLjiqT |
| TRX/USDT Pair | TPFvVvyvfSxPUpyhCZ4kewU1medy6gZjY4 |
| TRX/JST Pair | TTmRJr7AFvs8i1FnpXNtJ5nWDyCRgLAjEL |
| TRX/WIN Pair | TTcDPMWu4g8jL1v6h5w6GWD5zHBH9FyPAF |
| TRX/BTT Pair | TGDdy5L5oeJZQBGcUS45GW6owooPbxwmuE |
Mainnet WTRX
On TRON mainnet, the canonical Wrapped TRX address is: TNUC9Qb1rRpS5CbWLmNMxXBjyFoydXjWFR
src/config/contracts.ts and rebuild the frontend. Stale addresses will cause transactions to fail.
Token List
Default tokens displayed in the token selector are configured in src/config/tokens.ts. Each network has its own token list.
// src/config/tokens.ts
const NILE_TOKENS: TokenInfo[] = [
{
address: 'TRX', // Special identifier for native TRX
symbol: 'TRX',
name: 'TRON',
decimals: 6,
logoURI: getTokenLogoUrl('TRX'),
isNative: true, // Marks this as native token
},
{
address: 'TBaySNgxi2xL9Ccgb36UGfhceRreDNz89j',
symbol: 'WTRX',
name: 'Wrapped TRX',
decimals: 6,
logoURI: getTokenLogoUrl('WTRX'),
},
{
address: 'TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf',
symbol: 'USDT',
name: 'Test USDT',
decimals: 6,
logoURI: getTokenLogoUrl('USDT'),
},
// JST, WIN, BTT, and the TDEX token follow — see src/config/tokens.ts
];
To add a new token, append an entry to the relevant network's array. Token logos are resolved via the getTokenLogoUrl() function — add local icons in public/tokens/ or they'll fall back to a CDN.
Site Settings
Global site configuration is in src/config/site.ts:
export const siteConfig = {
name: 'TronDEX',
description: 'Decentralized Exchange on TRON Blockchain',
url: 'https://trondex.io',
links: {
github: 'https://github.com/trondex',
twitter: 'https://twitter.com/trondex',
docs: 'https://docs.trondex.io',
},
};
export const SWAP_FEE = 0.003; // 0.3%
export const LP_FEE_SHARE = 0.0025; // 0.25% to LPs
export const PROTOCOL_FEE_SHARE = 0.0005; // 0.05% protocol
export const DEFAULT_SLIPPAGE = 0.5; // 0.5%
export const DEFAULT_DEADLINE = 20; // 20 minutes
export const DEFAULT_FEE_LIMIT = 150_000_000; // 150 TRX in sun
Smart Contracts — Architecture Overview
The smart contract architecture follows the battle-tested Uniswap V2 model, adapted for the TRON Virtual Machine (TVM). There are 7 contracts organized into 3 layers:
Core Layer
- TronSwapFactory — Registry of all trading pairs. Maps token combinations to pair contract addresses.
- TronSwapPair — The AMM core. Holds reserves, executes swaps using constant-product formula, mints/burns LP tokens.
- WTRX — Wrapped TRX. Converts native TRX to a TRC-20 token so it can be used in pairs (all pairs are TRC-20/TRC-20).
Periphery Layer
- TronSwapRouter — User-facing contract. Handles complex operations: multi-hop swaps, TRX wrapping/unwrapping, slippage protection, deadline enforcement.
Incentive Layer
- TronSwapToken (TDEX) — Governance/reward TRC-20 token with 1B max supply, minter role system.
- TronSwapFarm — MasterChef-style farming. Stake LP tokens to earn TDEX rewards per block.
Supporting
- TransferHelper — Library for safe TRC-20 transfers with TVM-specific 0-value guards.
- Math / UQ112x112 — Math utilities for AMM calculations and TWAP oracle.
- TestUSDT — Simple TRC-20 for testnet testing (not for mainnet).
How a Swap Works (Flow)
User calls Router.swapExactTRXForTokens(amountOutMin, [WTRX, USDT], recipient, deadline)
│
├─ Router wraps TRX → WTRX (deposit)
├─ Router sends WTRX to Pair contract
├─ Router calls Pair.swap(0, amountOut, recipient, "0x")
│ │
│ ├─ Pair transfers USDT to recipient
│ ├─ Pair checks balances vs reserves
│ ├─ Pair verifies k invariant (with 0.3% fee)
│ └─ Pair updates reserves
└─ Done
Factory Contract
contracts/src/TronSwapFactory.sol
The Factory acts as a registry for all trading pairs. On TRON, pairs are deployed externally (not created by the factory) due to TVM limitations with CREATE2.
Key Functions
| Function | Access | Description |
|---|---|---|
registerPair(tokenA, tokenB, pair) | Owner only | Register an externally deployed pair |
getPair(tokenA, tokenB) | Public view | Look up pair address for two tokens |
allPairs(index) | Public view | Get pair by index |
allPairsLength() | Public view | Total number of registered pairs |
setFeeTo(address) | Owner only | Set protocol fee recipient |
setFeeToSetter(address) | Owner only | Transfer admin role |
createPair() | — | Always reverts on TVM (use registerPair) |
Pair Contract (AMM Core)
contracts/src/TronSwapPair.sol
Each Pair holds two TRC-20 token reserves and implements the constant-product AMM. It also serves as the LP token (TRC-20 "TSLP").
Key Functions
| Function | Description |
|---|---|
swap(amount0Out, amount1Out, to, data) | Execute a swap. Verifies k invariant after transfer. |
mint(to) | Deposit tokens and mint LP tokens proportional to contribution. |
burn(to) | Burn LP tokens and withdraw proportional share of reserves. |
getReserves() | Returns (reserve0, reserve1, blockTimestampLast). |
skim(to) | Transfer excess tokens (balance - reserve) to recipient. |
sync() | Force reserves to match actual token balances. |
initialize(token0, token1) | Set token pair (called once during setup). |
setFactory(factory) | Point pair to its factory (TVM-specific, for direct deployment). |
Fee Structure
- 0.3% swap fee — Deducted from every trade
- 0.25% goes to liquidity providers
- 0.05% goes to protocol fee recipient (if
feeTois set in Factory)
Router Contract
contracts/src/TronSwapRouter.sol
The Router is the main entry point for users. It handles TRX wrapping, slippage protection, deadline checks, and multi-hop routing.
Swap Functions
| Function | Description |
|---|---|
swapExactTRXForTokens | Swap exact TRX amount for tokens (minimum output) |
swapExactTokensForTRX | Swap exact tokens for TRX (minimum output) |
swapExactTokensForTokens | Swap exact tokens for tokens |
swapTRXForExactTokens | Swap TRX for exact token amount (maximum input) |
swapTokensForExactTRX | Swap tokens for exact TRX amount |
swapTokensForExactTokens | Swap tokens for exact token amount |
Liquidity Functions
| Function | Description |
|---|---|
addLiquidity | Add liquidity to a TRC-20/TRC-20 pair |
addLiquidityTRX | Add liquidity with native TRX (auto-wraps) |
removeLiquidity | Remove liquidity from a TRC-20/TRC-20 pair |
removeLiquidityTRX | Remove liquidity and receive native TRX (auto-unwraps) |
View Functions
| Function | Description |
|---|---|
getAmountsOut(amountIn, path) | Calculate expected output for a swap path |
getAmountsIn(amountOut, path) | Calculate required input for desired output |
getAmountOut(amountIn, reserveIn, reserveOut) | Single-pair output calculation |
quote(amountA, reserveA, reserveB) | Equivalent amount at current ratio |
WTRX Contract
contracts/src/WTRX.sol
Standard Wrapped TRX. Converts native TRX to TRC-20 for use in pairs. 6 decimals (matches TRX's sun precision).
| Function | Description |
|---|---|
deposit() | Send TRX, receive WTRX. Also triggered by direct TRX transfers. |
withdraw(amount) | Burn WTRX, receive native TRX back. |
TDEX Token
contracts/src/TronSwapToken.sol
Governance and reward token. Standard TRC-20 with minter role and 1 billion max supply.
| Function | Access | Description |
|---|---|---|
mint(to, amount) | Minters only | Mint new tokens (capped at MAX_SUPPLY) |
burn(amount) | Anyone | Burn own tokens |
setMinter(addr, status) | Owner only | Grant/revoke minting permission |
transferOwnership(addr) | Owner only | Transfer ownership |
Farm Contract
contracts/src/TronSwapFarm.sol
MasterChef-style yield farming. Users stake LP tokens and earn TDEX per block, distributed proportionally by pool weight.
Admin Functions
| Function | Description |
|---|---|
add(allocPoint, lpToken, depositFee, withUpdate) | Add a new farm pool. Deposit fee max 10%. |
set(pid, allocPoint, depositFee, withUpdate) | Update pool allocation and fee. |
setRewardPerBlock(amount) | Change reward emission rate. |
User Functions
| Function | Description |
|---|---|
deposit(pid, amount) | Stake LP tokens. Auto-harvests pending rewards. |
withdraw(pid, amount) | Unstake LP tokens. Auto-harvests pending rewards. |
emergencyWithdraw(pid) | Emergency unstake without rewards. |
pendingReward(pid, user) | View pending TDEX rewards. |
TVM Compatibility Notes
1. No CREATE2 for Pair Deployment
TVM does not support deterministic contract address computation via CREATE2. The Factory uses a registry pattern instead:
- Pairs are deployed as standalone contracts
- They are then registered with the Factory via
registerPair() - The Router looks up pairs via
Factory.getPair()instead of computing addresses
2. Zero-Value Transfer Rejection
TVM rejects .call() operations that transfer 0 value of a TRC-20 token. This breaks functions like skim() and swap() when one side has no excess or no output.
Solution: TransferHelper.sol includes guards at the start of every function:
function safeTransfer(address token, address to, uint256 value) internal {
if (value == 0) return; // TVM rejects 0-value CALL operations
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(0xa9059cbb, to, value)
);
require(success && (data.length == 0 || abi.decode(data, (bool))),
'TransferHelper: TRANSFER_FAILED');
}
3. EVM Version Must Be "paris"
Solidity 0.8.20 defaults to the Shanghai EVM which uses the PUSH0 opcode. TVM does not support PUSH0. The compiler is configured to target Paris:
// contracts/tronbox.js
compilers: {
solc: {
version: '0.8.20',
settings: {
evmVersion: 'paris', // Must be paris, NOT shanghai
optimizer: { enabled: true, runs: 200 },
},
},
},
4. Some Testnet Tokens Block Contract Transfers
Nile testnet's native USDT (TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf) rejects transfer() calls from smart contracts. This is why the project deploys its own TestUSDT for testnet. On mainnet, the real USDT works normally.
5. TronWeb v6 Response Format Varies
Contract call results may return named properties, underscore-prefixed properties, or array indices depending on the TronWeb version. Always use fallback chains:
const reserve0 = (reserves.reserve0 || reserves._reserve0 || reserves[0]).toString();
Deploy Contracts
Prerequisites
- A TRON wallet with sufficient TRX (5,000+ TRX recommended for all contracts + initial liquidity)
- Node.js installed
- The contracts are already compiled in
contracts/build/contracts/
Recompiling Contracts
If you modify any Solidity files, recompile with TronBox:
# Install TronBox globally
npm install -g tronbox
# Compile contracts
cd contracts
tronbox compile
# The compiled artifacts will be in contracts/build/contracts/
src/lib/abis/ so the frontend uses the correct interfaces. The ABI JSON is the "abi" field from each artifact in contracts/build/contracts/.
Step-by-Step Deployment Guide
The automated deployment script (scripts/deploy-all.mjs) handles all steps. To use it:
Edit the deployment script
Open scripts/deploy-all.mjs and update:
const PRIVATE_KEY = 'your-private-key-here';
const WALLET = 'your-TRON-address-here'; // T... format
const FEE_LIMIT = 1_500_000_000; // 1500 TRX, adjust if needed
Change the TronWeb endpoint for your target network:
// For Mainnet:
fullNode: 'https://api.trongrid.io',
// For Nile testnet:
fullNode: 'https://nile.trongrid.io',
Run the deployment
node scripts/deploy-all.mjs
The script will deploy all contracts sequentially and output the addresses. It also tests skim, swap, and reverse swap to verify everything works.
Update frontend configuration
Copy the addresses from the deployment output into src/config/contracts.ts:
// src/config/contracts.ts
nile: { // or 'mainnet'
factory: 'T...',
router: 'T...',
wtrx: 'T...',
tronSwapToken: 'T...',
farm: 'T...',
pair: 'T...',
usdt: 'T...',
},
Update token addresses
Update src/config/tokens.ts with the new WTRX and token addresses for your network.
Rebuild the frontend
npm run build
Deployment Script Steps (What It Does)
- Deploys TestUSDT (1B supply, 6 decimals) — skip for mainnet with real USDT
- Deploys TronSwapFactory with deployer as admin
- Deploys WTRX
- Deploys TronSwapRouter (pointing to Factory + WTRX)
- Deploys TronSwapPair directly
- Initializes pair with token0/token1 (sorted by address)
- Calls
pair.setFactory(factoryAddress) - Calls
factory.registerPair(tokenA, tokenB, pairAddress) - Approves quote token for Router
- Adds initial liquidity
- Tests skim, swap, and reverse swap
TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t and the canonical WTRX TNUC9Qb1rRpS5CbWLmNMxXBjyFoydXjWFR instead.
Adding New Trading Pairs
To add a new trading pair after initial deployment:
Deploy a new Pair contract
Deploy a new instance of TronSwapPair.sol to the network.
Initialize the pair
// Sort tokens by hex address (lower first = token0)
pair.initialize(token0, token1);
Set the factory
pair.setFactory(factoryAddress);
Register with factory
factory.registerPair(tokenA, tokenB, pairAddress);
Add initial liquidity
Approve both tokens for the Router, then call router.addLiquidity() or router.addLiquidityTRX().
Add tokens to frontend
Add any new token addresses to src/config/tokens.ts so they appear in the token selector.
Deploy Frontend
Build for Production
npm run build
This creates an optimized build in the .next/ directory.
Option 1: Self-Hosted (Node.js Server)
npm run build
npm start
# Runs on port 3000 by default
Use a reverse proxy (nginx, Caddy) to serve it on your domain with HTTPS.
Option 2: Vercel (Recommended)
- Push your project to a Git repository (GitHub, GitLab, Bitbucket)
- Import the project on vercel.com
- Add environment variables in the Vercel dashboard
- Deploy — Vercel auto-detects Next.js
Option 3: Static Export
For static hosting (Netlify, Cloudflare Pages, S3), add to next.config.ts:
const nextConfig = {
output: 'export',
};
export default nextConfig;
Then npm run build generates static files in the out/ directory.
Frontend Pages
| Route | File | Description |
|---|---|---|
/ | app/page.tsx | Landing page with hero, stats, features, top pools, and CTAs |
/swap | app/swap/page.tsx | Token swap interface with price quotes and confirmation |
/liquidity | app/liquidity/page.tsx | Pool list with TVL, volume, APR. Tabs: All Pools / My Positions |
/liquidity/add | app/liquidity/add/page.tsx | Add liquidity form with dual token inputs |
/liquidity/remove/[addr] | app/liquidity/remove/[pairAddress]/page.tsx | Remove liquidity with percentage slider |
/farms | app/farms/page.tsx | Farming dashboard with stake/unstake/harvest |
/portfolio | app/portfolio/page.tsx | User portfolio: tokens, LP positions, farming, tx history |
Frontend Components
Swap Components src/components/swap/
| Component | Description |
|---|---|
| swap-card.tsx | Main swap interface container. Orchestrates the full swap flow. |
| token-input.tsx | Amount input field with token selector button and balance display. |
| token-select-modal.tsx | Searchable modal for picking tokens. Shows balances and favorites. |
| swap-button.tsx | Smart button: Connect Wallet / Select Token / Enter Amount / Approve / Swap. |
| swap-details.tsx | Expandable details: route, fee, price impact, minimum received. |
| swap-confirmation.tsx | Confirmation dialog with preview/pending/success/error states. |
| price-display.tsx | Exchange rate display with toggle direction. |
| slippage-settings.tsx | Popover for slippage tolerance and deadline configuration. |
Liquidity Components src/components/liquidity/
| Component | Description |
|---|---|
| pool-list.tsx | Filterable/sortable list of all available liquidity pools. |
| pool-card.tsx | Individual pool card showing pair, TVL, volume, APR. |
| pool-stats.tsx | Aggregate liquidity statistics (total TVL, volume, fees). |
| pool-position.tsx | User's position in a specific pool (share, value, earnings). |
| add-liquidity-form.tsx | Dual token input form with ratio display and pool share preview. |
| remove-liquidity-form.tsx | Percentage slider (25/50/75/100%) with token amount preview. |
Farm Components src/components/farms/
| Component | Description |
|---|---|
| farm-list.tsx | All farms with filters: active/ended, staked-only toggle. |
| farm-card.tsx | Expandable farm card with APR, TVL, earned rewards, stake/unstake. |
| stake-modal.tsx | Modal dialog to stake LP tokens into a farm. |
| unstake-modal.tsx | Modal dialog to unstake LP tokens from a farm. |
| harvest-button.tsx | Claim pending TDEX rewards button. |
Wallet Components src/components/wallet/
| Component | Description |
|---|---|
| connect-button.tsx | Wallet connect/disconnect button with address display. |
| wallet-modal.tsx | Wallet selection dialog (TronLink, WalletConnect). |
| account-info.tsx | Connected account details: address, balance, TronScan link. |
| network-badge.tsx | Current network indicator badge. |
Frontend Hooks
All hooks are in src/hooks/. They use TanStack Query for caching and automatic refetching.
| Hook | Description | Refetch |
|---|---|---|
useTronWeb() | Returns TronWeb instance (wallet-injected or read-only) | — |
useWalletInfo() | Wallet address, connection status, TRX balance | — |
useTokenBalance(token) | TRC-20 or native TRX balance for connected wallet | 30s |
useTokenAllowance(token, spender) | Check allowance + approve mutation | On demand |
useTokenList() | Available tokens for current network with search | — |
useTokenPrice(token) | Token USD price via pool reserves | 30s |
useSwapQuote() | Swap quote: output amount, price impact, minimum received | 12s |
useSwap() | Execute swap transaction mutation | — |
usePoolData(pair, t0, t1) | Pool reserves, total supply for a specific pair | 12s |
useAllPools() | All registered pools with reserves | 30s |
useLiquidity() | Add/remove liquidity transaction mutations | — |
useFarmData() | Farm pools, APR, TVL, pending rewards | 15s |
useFarm() | Stake/unstake/harvest farm mutations | — |
usePortfolio() | Aggregated portfolio: tokens, positions, farming | 30s |
useTransaction() | Transaction submission and confirmation polling | — |
State Management (Zustand)
| Store | Persisted | State |
|---|---|---|
useSwapStore |
No | tokenIn, tokenOut, typedValue, independentField, switchTokens(), reset() |
useSettingsStore |
Yes (localStorage) | slippage (0.5%), deadline (20 min), expertMode, network ("nile") |
useTransactionStore |
No | transactions[] with txId, description, status, timestamp |
tronswap-settings. After changing contract addresses, users should clear their localStorage or the frontend may use stale cached network settings.
Providers
All providers are composed in src/providers/app-providers.tsx and wrapped around the app in src/app/layout.tsx:
| Provider | Purpose |
|---|---|
ThemeProvider | Dark/light mode via next-themes. Default: dark. |
QueryProvider | TanStack Query client for data fetching/caching. |
WalletProvider | TRON wallet adapters: TronLink + WalletConnect. |
Toaster | Sonner toast notifications for transaction feedback. |
Customization — Branding & Theming
Site Name & Metadata
Edit src/config/site.ts to change the site name, description, URLs, and social links. Page-specific SEO metadata is in each page's metadata export.
Colors & Theme
The app uses Tailwind CSS 4 with CSS variables for theming. Edit the theme in src/app/globals.css:
- The accent color gradient uses
red-500torose-600throughout the components - Search for
from-red-500andto-rose-600in components to change the primary gradient - Dark/light theme variables are defined in globals.css
Logo
Replace the logo in src/components/layout/header.tsx. The current logo is text-based. To use an image, replace the text with an <Image> component.
Token Icons
Place SVG icons in public/tokens/ (e.g., trx.svg, usdt.svg). Register them in the localIcons map in src/config/tokens.ts.
Customization — Fees & Parameters
Swap Fee (On-Chain)
The 0.3% swap fee is hardcoded in TronSwapPair.sol at line 208:
uint256 balance0Adjusted = balance0 * 1000 - amount0In * 3;
uint256 balance1Adjusted = balance1 * 1000 - amount1In * 3;
To change to 0.2%, replace * 3 with * 2 (and 997 to 998 in the Router's getAmountOut).
Frontend Display Fee
Update the display values in src/config/site.ts to match your on-chain fee.
Farm Rewards
Farm reward rate is set via farm.setRewardPerBlock(amount). No redeployment needed — just call the function from the owner wallet.
Default Slippage & Deadline
Edit DEFAULT_SLIPPAGE and DEFAULT_DEADLINE in src/config/site.ts. Users can override these in the UI.
Fee Limit
DEFAULT_FEE_LIMIT in src/config/site.ts controls the maximum TRX spent on energy for each transaction. 150 TRX is adequate for most operations. Increase for complex multi-hop swaps.
Customization — Adding Tokens
Add a Token to the Token Selector
Edit the appropriate network array in src/config/tokens.ts:
{
address: 'TXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', // TRC-20 contract address
symbol: 'MYTOKEN',
name: 'My Token',
decimals: 18, // Check the token contract for correct decimals
logoURI: getTokenLogoUrl('MYTOKEN'),
},
Add a Token Logo
- Place an SVG or PNG icon in
public/tokens/mytoken.svg - Add it to the
localIconsmap insrc/config/tokens.ts:const localIcons: Record<string, string> = { TRX: '/tokens/trx.svg', MYTOKEN: '/tokens/mytoken.svg', // ... };
Create a Trading Pair
After adding the token, you need to deploy a Pair contract and register it (see Adding New Pairs).
Customization — Wallet Support
Wallet adapters are configured in src/providers/wallet-provider.tsx. The app ships with:
- TronLink — Browser extension (most popular)
- WalletConnect — Mobile wallet scanning (requires Project ID)
To add more wallets, import additional adapters from @tronweb3/tronwallet-adapters and add them to the adapters array.
Protocol Constants Reference
| Constant | Value | Location |
|---|---|---|
| Swap Fee | 0.3% (997/1000) | TronSwapPair.sol, Router.sol |
| LP Fee Share | 0.25% (5/6 of fee) | TronSwapPair.sol |
| Protocol Fee Share | 0.05% (1/6 of fee) | TronSwapPair.sol |
| Minimum Liquidity | 1,000 LP tokens | TronSwapPair.sol |
| TDEX Max Supply | 1,000,000,000 | TronSwapToken.sol |
| Max Farm Deposit Fee | 10% (1000 basis points) | TronSwapFarm.sol |
| WTRX Decimals | 6 (matches TRX sun) | WTRX.sol |
| Default Slippage | 0.5% | src/config/site.ts |
| Default Deadline | 20 minutes | src/config/site.ts |
| Default Fee Limit | 150 TRX (150M sun) | src/config/site.ts |
| Balance Refetch | 30 seconds | src/hooks/ |
| Reserve Refetch | 12 seconds | src/hooks/ |
Troubleshooting
TransferHelper: TRANSFER_FAILED
Cause: The TRC-20 transfer() call from a contract failed.
- Ensure
TransferHelper.solhas zero-value guards (if (value == 0) return;) - On Nile testnet, don't use the native USDT — use your own TestUSDT
- Check that the token contract allows transfers from other contracts
Transaction Uses Wrong Contract Address
Cause: Browser cache or stale build serving old addresses.
- Stop the dev server and delete
.next/folder - Rebuild:
npm run build - Hard refresh browser: Cmd+Shift+R (Mac) / Ctrl+Shift+R (Windows)
- Clear localStorage: DevTools → Application → Local Storage → delete
tronswap-settings
Swap Reverts with "TronDEX: K"
Cause: The constant-product invariant check failed. The fee wasn't properly accounted for.
- Ensure the Router's
getAmountOutuses 997/1000 matching the Pair's fee - Check for rounding errors in the frontend's amount calculations
TronLink Not Detected
Cause: TronLink extension not installed or not on the correct network.
- Install TronLink from Chrome Web Store
- Switch TronLink to the same network as your app (Nile for testnet)
- Refresh the page after switching networks
Compilation Error: PUSH0 Not Supported
Cause: Wrong EVM version in compiler config.
- Ensure
evmVersion: 'paris'is set incontracts/tronbox.js - Do NOT use Shanghai or later EVM targets
OUT_OF_ENERGY on Deployment
Cause: Insufficient TRX for energy costs.
- Increase wallet TRX balance (deployment needs ~5,000+ TRX)
- Consider staking TRX for energy on mainnet to reduce costs
- Increase
FEE_LIMITin the deploy script if transactions are hitting the limit
getReserves() Returns Wrong Format
Cause: TronWeb v6 inconsistent response format.
- Always use fallback chain:
(res.reserve0 || res._reserve0 || res[0]) - Check all hooks that call
getReserves()
Security Notes
Private Keys
- The deploy script contains a hardcoded test private key. Never use this key on mainnet.
- Use environment variables or a hardware wallet for production deployment.
- The deployment wallet becomes the Factory admin (
feeToSetter). Guard this key carefully.
Smart Contract Security
- Contracts are based on Uniswap V2 — a battle-tested and heavily audited codebase.
- The key modifications are: registry-based Factory, zero-value transfer guards, TVM-compatible Pair deployment.
- Consider a professional audit before deploying to mainnet with significant value.
- The reentrancy guard (
lockmodifier) protects all state-changing Pair functions.
Frontend Security
- All blockchain interactions go through the user's wallet (TronLink). The frontend never handles private keys.
- Slippage protection prevents sandwich attacks (users set their own tolerance).
- Transaction deadlines prevent stale transactions from executing at unfavorable prices.
Admin Privileges
The deployer wallet has these admin capabilities:
- Factory: Register new pairs, set protocol fee recipient, transfer admin role
- Farm: Add/modify pools, change reward rate, transfer ownership
- TDEX Token: Grant/revoke minting permissions, transfer ownership
Consider transferring these to a multisig wallet or timelock contract for production.
Changelog
1.0.0 — September 2026
- Initial release.
- 7 Solidity contracts (Factory, Pair, Router, WTRX, TDEX token, Farm) deployed and verified on the TRON Nile testnet.
- Next.js 16 / React 19 frontend: swap, liquidity, farms, and portfolio.
- TronLink & WalletConnect integration.
- Full internationalization — all copy in
src/locales/. - One-command, resumable deployment script.
Credits & Sources
TronDEX is original source code. It builds on the following open, permissively licensed resources — all cleared for redistribution in a commercial item.
| Resource | Used for | License |
|---|---|---|
| Next.js, React, React DOM | App framework & UI runtime | MIT |
| Tailwind CSS, tw-animate-css | Styling | MIT |
| Radix UI | Accessible UI primitives | MIT |
| TronWeb & @tronweb3 wallet adapters | TRON blockchain & wallet connectivity | MIT |
| TanStack Query, Zustand | Data fetching & state | MIT |
| lucide-react | Interface icons | ISC |
| cryptocurrency-icons | Token logos | CC0 1.0 (public domain) |
| Space Mono & JetBrains Mono | Typography (self-hosted) | SIL Open Font License 1.1 |
| AMM design | Uniswap V2 constant-product model, re-implemented for the TVM | Original implementation |
A per-file provenance list is included in docs/asset-license-ledger.md. The TronDEX brand mark, favicon, and token monograms (JST, WIN, TDEX) are original and ship with the item.
Support
Support covers installation help, bug fixes, and answering questions about the item's features. It does not cover custom development or third-party plugin integration.
- Read this documentation and the live demo first — most questions are answered here.
- Contact us through your Envato purchase's item support tab.
- When reporting an issue, include your Node version, the exact command, and the full error output.
If this item helped you, a rating on your Envato Downloads page is genuinely appreciated.
TronDEX Documentation — v1.0.0 — Built with Next.js, Solidity, and TronWeb