Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.privy.io/llms.txt

Use this file to discover all available pages before exploring further.

Transatron is a Tron RPC provider that delegates the energy and bandwidth required to process a transaction, so end users can transact on Tron without holding TRX. Apps integrate Transatron as a drop-in replacement for the Tron full node and select a fee-payment mode that fits their UX. This recipe combines Privy’s Tron wallet support with Transatron’s gas sponsorship to broadcast TRX-less transfers from a user’s embedded wallet.

Resources

Transatron docs

Official Transatron integration documentation.

Tron raw signing

How Privy signs Tron transactions via raw_sign.

Prerequisites

  • A funded Transatron account and a Spender API key issued from the dashboard. The Spender key authorizes fee deduction from the app’s prepaid TFN/TFU balance on every broadcast.
Keep the Transatron API key on the server. Exposing it to a browser or mobile binary lets any caller spend the app’s Transatron balance.

How fee payment works

Transatron supports four fee-payment modes:
ModeWhen to useUser holds TRX?
Internal accountDefault, simplest integration. Broadcasting through the Transatron RPC with a Spender key auto-deducts fees from the app’s prepaid TFN/TFU balance. No per-transaction setup required.No
Instant paymentThe user wallet holds a small TRX or USDT balance to cover Transatron’s per-tx fee. Primarily for non-custodial wallet integrations.Yes (small)
CouponPer-transaction spend cap. The backend issues a coupon backed by its Transatron balance. Typically used for promos and individual discounts.No
BypassFallback mode. The sender’s wallet burns TRX directly for fees as on a vanilla Tron node.Yes
All modes except bypass rely on broadcasting through the Transatron RPC. Submitting the same signed transaction to a vanilla Tron node bypasses Transatron’s resource delegation logic, and Tron charges fees as usual. This recipe focuses on the internal account mode — the simplest integration path. Broadcasting through the RPC with a Spender key is all that’s needed to sponsor fees. For other modes, see the Transatron integration guide.

1. Create a Tron wallet for the user

Privy supports Tron at the Tier 2 level. Create a wallet with chain_type: 'tron'. The wallet address can receive TRX, USDT, and other TRC-20 assets.
Newly created Tron addresses may require on-chain activation before some sending flows work reliably. Fund the address with a small TRX amount first if activation related errors appear.

2. Configure TronWeb to use the Transatron RPC

Point TronWeb at https://api.transatron.io and attach the Spender API key as a header. All subsequent operations — fee estimation, simulation, and broadcasts — flow through Transatron. The Spender key on the connection authorizes automatic fee deduction from the app’s prepaid balance on every broadcast.
import {TronWeb, providers} from 'tronweb';

const TRANSATRON_RPC = 'https://api.transatron.io';
const TRANSATRON_TIMEOUT = 60_000;
const headers = {'TRANSATRON-API-KEY': process.env.TRANSATRON_API_KEY!};

const tronWeb = new TronWeb({
  fullNode: new providers.HttpProvider(TRANSATRON_RPC, TRANSATRON_TIMEOUT, '', '', headers),
  solidityNode: new providers.HttpProvider(TRANSATRON_RPC, TRANSATRON_TIMEOUT, '', '', headers),
  eventServer: new providers.HttpProvider(TRANSATRON_RPC, TRANSATRON_TIMEOUT, '', '', headers)
});

3. Sign Tron transactions with Privy

Privy’s raw_sign returns a 64-byte ECDSA signature, but Tron expects 65 bytes — the trailing recovery byte is either 0x1b or 0x1c. Signing is the only step in the flow that can run on the client; building and broadcasting still happen on the server, since both require the Transatron API key.

4. Broadcast a sponsored transaction

With the internal-account mode, broadcasting through the Transatron RPC is all that’s needed to sponsor fees. The Spender key on the connection authorizes the charge — no coupon creation or additional per-transaction setup is required. The code below runs entirely on the server. If signing happens in a React client (per step 3), replace the inline signTronTransaction(...) call with a roundtrip — return the unsigned transaction’s txID to the client, receive the 64-byte signature back, and finalize via attachTronSignature(...) before broadcasting.
1

Compute the Tron fee limit

Tron rejects transactions whose fee_limit is lower than the energy required to execute them. Use triggerConstantContract to estimate energy_used and multiply by the live energy_fee from chain parameters. This is the Tron-side fee limit that gets baked into the signed transaction. This example uses USDT on Tron mainnet.
const USDT_CONTRACT = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t'; // USDT on Tron mainnet

async function estimateFeeLimit({
  ownerAddress,
  recipientAddress,
  amountBaseUnits
}: {
  ownerAddress: string;
  recipientAddress: string;
  amountBaseUnits: string;
}): Promise<number> {
  const ownerHex = tronWeb.address.toHex(ownerAddress);
  const contractHex = tronWeb.address.toHex(USDT_CONTRACT);

  const constant = await tronWeb.transactionBuilder.triggerConstantContract(
    contractHex,
    'transfer(address,uint256)',
    {},
    [
      {type: 'address', value: recipientAddress},
      {type: 'uint256', value: amountBaseUnits}
    ],
    ownerHex
  );

  const params = await tronWeb.trx.getChainParameters();
  const energyFee = params.find((p) => p.key === 'getEnergyFee')?.value ?? 420;
  const energyUsed = constant.energy_used ?? 0;

  return Math.ceil(energyUsed * energyFee * 1.1); // 10% buffer
}
2

Build, sign, and broadcast the transfer

Build the TRC-20 transfer locally, sign the txID with Privy, and broadcast through the Transatron RPC. The Spender key on the connection handles fee payment automatically.
async function sendSponsoredTransfer({
  walletId,
  walletAddress,
  recipientAddress,
  amountBaseUnits,
  feeLimit
}: {
  walletId: string;
  walletAddress: string;
  recipientAddress: string;
  amountBaseUnits: string;
  feeLimit: number;
}) {
  const ownerHex = tronWeb.address.toHex(walletAddress);
  const contractHex = tronWeb.address.toHex(USDT_CONTRACT);

  const built = await tronWeb.transactionBuilder.triggerSmartContract(
    contractHex,
    'transfer(address,uint256)',
    {feeLimit, callValue: 0},
    [
      {type: 'address', value: recipientAddress},
      {type: 'uint256', value: amountBaseUnits}
    ],
    ownerHex
  );

  if (!built.transaction) {
    throw new Error('Failed to build transfer transaction');
  }

  const signed = await signTronTransaction({
    tronWeb,
    walletId,
    walletAddress,
    transaction: built.transaction as Types.SignedTransaction<Types.TriggerSmartContract>
  });

  return tronWeb.fullNode.request('wallet/broadcasttransaction', signed, 'post');
}
The broadcast response includes a nested transatron object. Fields can vary by mode and API version (for example tx_fee_rtrx_account, code, or zero-fee counters), but the key signal is a sponsored/free-fee outcome instead of a Tron burn from the sender wallet.
3

Orchestrate the full flow

Chain the helpers from the previous steps to send a sponsored TRC-20 transfer. With internal-account sponsorship, transaction fees can be covered by Transatron instead of burning TRX from the sender wallet.
const feeLimit = await estimateFeeLimit({
  ownerAddress,
  recipientAddress,
  amountBaseUnits
});

const result = await sendSponsoredTransfer({
  walletId,
  walletAddress: ownerAddress,
  recipientAddress,
  amountBaseUnits,
  feeLimit
});

Operating the business account

Use the following Transatron API endpoints to check account balance, review spending history, and fetch current pricing.
Query the current TFN/TFU balance available for sponsoring transactions:
const config = await tronWeb.fullNode.request<{
  balance_rtrx: number;
  balance_rusdt: number;
}>('api/v1/config', {}, 'get');

console.log('TFN balance:', config.balance_rtrx);
console.log('TFU balance:', config.balance_rusdt);
Retrieve recent fee charges against the account to audit per-transaction costs:
const ordersResponse = await tronWeb.fullNode.request<{
  orders?: Array<{
    order_id: string;
    order_date: string;
    amount_trx: number;
    charge_token: 'RTRX' | 'RUSDT';
  }>;
  pagination?: {limit: number; offset: number; total: number};
}>(
  'api/v1/orders',
  {
    limit: 50,
    offset: 0,
    from_date: '2026-01-01T00:00:00Z',
    to_date: '2026-03-01T00:00:00Z'
  },
  'get'
);
const orders = ordersResponse.orders ?? [];

for (const order of orders) {
  console.log(
    `Order ${order.order_id}: ${order.amount_trx} sun (${order.charge_token}) at ${order.order_date}`
  );
}
Read pricing from the same GET /api/v1/config response:
const config = await tronWeb.fullNode.request<{
  activation_price: number;
  energy_price_per_unit: number;
  bandwidth_price_per_unit: number;
}>('api/v1/config', {}, 'get');

console.log('Activation price:', config.activation_price, 'sun');
console.log('Energy price:', config.energy_price_per_unit, 'sun per unit');
console.log('Bandwidth price:', config.bandwidth_price_per_unit, 'sun per unit');
These account-management endpoints require the ADMIN (spender) API key. For full endpoint details, see the Transatron account management docs.