Testing USDT payouts before mainnet: what Nile changes and what a sandbox simulates
A payout integration should meet its first failure somewhere cheaper than mainnet, and on TRON there are two such places. Nile is a public testnet: a real chain where transactions are signed and land in blocks, running on parameters of its own. A sandbox such as ours copies the API over a simulated chain, which gives up the real network and gains the outcomes a real network will not produce on request. We read the chain parameters of mainnet and Nile on 3 September 2026 and signed transactions on Nile the next day.
What Nile shares with mainnet
Nile answers the same getchainparameters call as mainnet, and the parameters that price a transfer came back identical. Energy costs 100 sun a unit on both networks, so a transfer that runs short of energy burns TRX at the same rate on each. Free bandwidth, the fee for creating an account, the memo fee and the three dynamic energy parameters match as well.
| Chain parameter, read 3 September 2026 | Mainnet | Nile |
|---|---|---|
Energy fee in sun per unit, getEnergyFee | 100 | 100 |
Free bandwidth per account, getFreeNetLimit | 600 | 600 |
Account creation fee in sun, getCreateAccountFee | 100,000 | 100,000 |
Memo fee in sun, getMemoFee | 1,000,000 | 1,000,000 |
Dynamic energy threshold, getDynamicEnergyThreshold | 5,000,000,000 | 5,000,000,000 |
Dynamic energy increase factor, getDynamicEnergyIncreaseFactor | 2,000 | 2,000 |
Dynamic energy maximum factor, getDynamicEnergyMaxFactor | 34,000 | 34,000 |
Unstaking delay in days, getUnfreezeDelayDays | 14 | 1 |
Longest delegation lock in blocks, getMaxDelegateLockPeriod | 864,000 | 144,000 |
Maintenance interval, getMaintenanceTimeInterval | 21,600,000 | 1,800,000 |
CPU time ceiling of one transaction, getMaxCpuTimeOfOneTx | 80 | 160 |
What Nile changes
For anyone who handles energy, the first difference is unstaking: it takes one day on Nile against fourteen on mainnet, so a test that freezes TRX and then withdraws it finishes thirteen days sooner than the same sequence would in production. The longest lock a delegation can carry is 144,000 blocks on Nile, five days at three seconds a block, against 864,000 blocks, thirty days, on mainnet. A lock longer than five days cannot be rehearsed on Nile at all; what a lock refuses is the same on both networks.
Eight of the parameters mainnet returned carry a different value on Nile. Besides those two, they are the maintenance interval, the CPU ceiling in the table, and four that govern block producers, proposals and contract features. We have not traced any of those six into a payout flow.
Staking also yields a different amount of energy, because each network divides the same energy limit among its own total stake, and Nile's stake is far smaller. In both of our Nile runs on 4 September, the stake we delegated showed up on the receiving account as 7,376 units of energy. The same stake on mainnet, at the total read a day earlier, comes to 958 units, so Nile hands out nearly eight times as much. A stake sized against Nile would leave a mainnet wallet short.
| Energy from staking | Mainnet, 3 September 2026 | Nile, 4 September 2026 |
|---|---|---|
Energy limit of the whole network, TotalEnergyLimit | 180,000,000,000 | 180,000,000,000 |
Total stake for energy, TotalEnergyWeight | 18,770,236,993 | 2,440,088,105 |
| Energy on the receiver from 100 TRX delegated | 958 units, computed | 7,376 units, measured |
Test USDT is a different contract
Payout code carries the address of the USDT contract it calls. On 27 October 2026 we asked a Nile node for the contract at the mainnet USDT address, TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t, and the answer was an empty object, {}: no contract at that address on the testnet. Test tokens on Nile come from another contract at another address, so the contract address belongs in configuration next to the node URL, and a build that hard-codes it will call the wrong address on one of the two networks.
We have not measured what one transfer of a Nile test token costs in energy. Nile charges the same fee per unit, but the token is another contract, so nothing on Nile confirms the mainnet figures of about 65,000 units to a holder and about 131,000 units to an address with no USDT. Test TRX comes from faucets, and they ration it: the one we used in September allowed one request per wallet and per IP every 24 hours.
A signed transaction also stays on the network it was built for. Every TRON transaction carries a reference to a recent block of its own chain, and our API checks that reference against mainnet before it buys any energy. A mode B transaction built against Nile is refused with a 400 and details.reason set to ref_block_unknown. When the chain does not answer our check, the order is accepted unchecked and the node's refusal after delivery is billed, so build every transaction against the current mainnet block before you send it.
What the sandbox simulates
Our sandbox answers at https://sandbox.nrg.market/v1 and runs the same code as production over test money, a simulated chain and simulated energy vendors. Keys there start with nrg_test_ and come from the sandbox cabinet, where registration is self-serve. The two stands share nothing: separate databases, balances, webhooks and secrets. When the integration works there, you change the base URL and the key; the API flow is the same on both.
Test money arrives without a faucet. Confirming the email credits a starting balance, and POST /v1/sandbox/deposit credits more down the same path a real deposit takes: a deposit row in the ledger with a txid that starts sandbox-, and a real deposit.credited webhook. On production that path does not exist and answers 404.
| Test money in the sandbox | Per the API contract |
|---|---|
| On confirming the email, or the first Google sign-in | 10000 TRX |
One call of POST /v1/sandbox/deposit | up to 100000 TRX |
| Deposit calls per client per UTC day | 10 |
A testnet will not produce a particular outcome on request. The sandbox wires a few addresses to fixed behaviour, the way test card numbers work: valid TRON addresses with no private key behind them. The recipient decides the energy kind and what happens after ready; the sender decides how the purchase and the delegation go.
| Address | Role | What the sandbox does |
|---|---|---|
TLLmUhBYgU125KkPpeTdP1vz1zqhoZwn9v | Recipient | Holds no USDT, so kind: double. It is also not activated, and it stays empty however many transfers land on it. |
TDUvBqzR3cYY6zYopYdJ9jWrxQRs9QmvQM | Recipient | No transfer ever appears. The item waits at ready, becomes expired at send_before and is charged, as in production. |
TKLeQhXSUba1GG1wdznyMc49oqModZ8Fbm | Recipient | On the USDT blacklist: the order is refused with 422 blacklisted_recipient. |
TQ6ey8qT87bnzBJXj7gVTGCkrU4wUJ1EWQ | Sender | The purchase fails at every vendor. The item ends failed with purchase_failed, and the hold is released. |
TYWZsWdM9u8QKJTi6XEmenpvCPwg1xmPCC | Sender | The first vendor is unavailable and the failover succeeds. Nothing in the response says so. |
TNhq25t5XTEuk3mC9cTcAGB5rr3xuCkGyr | Sender | Delegation confirms after about 25 seconds, for the code that has to wait. |
| Any other valid address | Either | A recipient that holds USDT, and a delegation that confirms in 2 to 8 seconds. |
The two sides combine, so a batch that mixes the failing sender with ordinary ones ends partially_completed with nothing special asked for (what that status means for the invoice). The scenario senders are shared by every client of the stand, so when the timing is the thing under test, use a fresh sender address of your own: it gets the ordinary 2 to 8 seconds, and its delegations are private to it.
Prices on the stand are the live ones. The sandbox tariff follows production's about two minutes behind, three at the worst, so an estimate rehearsed there returns the price production quoted two or three minutes earlier. Mode B needs no real key: the simulated chain does not check signatures, so a transaction signed by any throwaway key is parsed as production parses it and walks through broadcasting, broadcasted and confirmed, with the broadcast confirming in about three seconds.
What only mainnet shows
The sandbox cannot prove the part the chain does: energy never actually arrives anywhere on it, and a delegation confirmed there is a fact about our simulator. Nile cannot settle it for our service either, because we sell no energy on any testnet. You learn in production whether real energy lands on a real wallet, and whether the transfer then goes through without burning TRX.
Some branches cannot be produced on either stand by any request: 503 capacity_unavailable, and the item errors broadcast_failed, transaction_reverted and broadcast_window_missed. Each depends on energy supply, on the chain, or on the service being paused by us. Write that handling from the contract and the webhook bodies, and review it as code that has never run.
A good part of production costs nothing to exercise. POST /v1/estimate takes up to 500 recipients and returns the same kind, energy_units and warnings an order would compute, and POST /v1/webhooks/{webhook_id}/test sends your receiver a real signed delivery. POST /v1/orders costs real TRX in every mode, which makes a first live order of one transfer the last rehearsal and the only one that shows energy landing.
Every scenario address in this post answers on the stand, over test money and your own nrg_test_ key: open the sandbox cabinet and issue one →