Tron (TRX) Payment Acceptance Setup

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Tron (TRX) Payment Acceptance Setup
Simple
~2-3 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1217
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1046
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Setting Up Payment Acceptance in Tron (TRX)

Tron is popular for payment systems for one reason: transaction fees for TRC-20 transfers (USDT) are close to zero if the sender has sufficient Energy and Bandwidth. This makes it the preferred channel for small payments and high-volume transactions in developing markets. Setting up payment acceptance is a straightforward task, but there are specifics to working with Tron's resource model.

Resource Model: Energy and Bandwidth

Tron has no familiar gas. Instead — two resources:

Bandwidth — for regular TRX transfers and account activation. Each account gets 600 Bandwidth per day for free. If insufficient — TRX is deducted (0.1 TRX per 1000 Bandwidth).

Energy — for interacting with smart contracts, including TRC-20 transfers. Not given for free. Sources:

  • Freeze TRX → get Energy
  • Buy Energy directly from delegators (cheaper than freezing for one-off operations)
  • If no Energy — transaction burns TRX directly

For USDT TRC-20 receipt: the sender spends Energy from their account. Your receiving address does not spend Energy. But there's a nuance: first interaction with a smart contract on a new account requires activation (1 TRX). If a user transfers from a new wallet — make sure their account is activated.

Setup via TronWeb

const TronWeb = require('tronweb');

const tronWeb = new TronWeb({
  fullHost: 'https://api.trongrid.io',  // or own node
  headers: { 'TRON-PRO-API-KEY': process.env.TRONGRID_API_KEY },
  privateKey: process.env.TRON_PRIVATE_KEY,
});

// Get TRC-20 balance (USDT)
const USDT_CONTRACT = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t';

async function getUsdtBalance(address: string): Promise<bigint> {
  const contract = await tronWeb.contract().at(USDT_CONTRACT);
  const balance = await contract.balanceOf(address).call();
  return BigInt(balance.toString());
}

TronGrid — official public API. Limits without API key: 15 req/sec, with key (free): 1000 req/sec.

Payment Address Generation

HD Wallet for Tron uses coin type 195 per BIP-44:

import { ethers } from 'ethers';
import TronWeb from 'tronweb';

function deriveTronAddress(mnemonic: string, index: number): string {
  const hdNode = ethers.HDNodeWallet.fromMnemonic(
    ethers.Mnemonic.fromPhrase(mnemonic)
  ).derivePath(`m/44'/195'/0'/0/${index}`);

  // Tron address — Ethereum address with different prefix (T instead of 0x)
  return TronWeb.address.fromPrivateKey(hdNode.privateKey.slice(2));
}

Tron address technically matches Ethereum address, only displayed in Base58Check with prefix T.

Monitoring Incoming Transactions

async function pollTrc20Transactions(address: string, fromTimestamp: number) {
  const response = await fetch(
    `https://api.trongrid.io/v1/accounts/${address}/transactions/trc20` +
    `?min_timestamp=${fromTimestamp}&contract_address=${USDT_CONTRACT}&limit=200`,
    { headers: { 'TRON-PRO-API-KEY': process.env.TRONGRID_API_KEY! } }
  );

  const data = await response.json();

  for (const tx of data.data) {
    if (tx.to === address && tx.type === 'Transfer') {
      await processPayment({
        txId: tx.transaction_id,
        amount: BigInt(tx.value),  // in sun, 1 USDT = 1_000_000 sun
        confirmations: tx.confirmed ? 20 : 0,
      });
    }
  }
}

Tron finalizes blocks through DPOS consensus. A transaction is considered confirmed at approximately 19 blocks (~57 sec). For payments: wait for confirmed: true from the API — this is sufficient, the probability of reorg in Tron is extremely low.

Notification Configuration

TronGrid supports webhook subscriptions via TronWatch or third-party services. Alternatively — Moralis Streams with Tron support:

// Example with Moralis Streams
const stream = await Moralis.Streams.add({
  chains: [EvmChain.TRON_MAINNET],
  description: "USDT TRC-20 payments",
  tag: "payments",
  webhookUrl: "https://your-api.com/tron-webhook",
  includeContractLogs: true,
  abi: ERC20_ABI,
  topic0: ["Transfer(address,address,uint256)"],
  advancedOptions: [
    { topic0: "Transfer(address,address,uint256)", filter: { "eq": ["to", receivingAddress] } }
  ],
});

Setup Checklist

  • TronGrid API key registered and added to config
  • Addresses generated from HD Wallet with coin type 195
  • TRC-20 Transfer event monitoring on USDT contract TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t
  • Amounts stored in bigint (avoid float — loss of precision)
  • Confirmation: confirmed: true or 20+ blocks
  • Test with real transaction on small amount before production