txID, and broadcasts the signed bytes itself. Your wallet only verifies what it was given and signs it — it never rebuilds, re-serializes, or submits the transaction.
This guide applies whether you integrate with the Wallet Pay SDK or directly with the Gateway API (API-first). The signing requirements are identical — Tron actions arrive as
walletRpc actions, and the signed result is returned in the results array. The code samples below use SDK method names; if you are integrating API-first, the equivalents are:Everything else in this guide — advertising Tron accounts, routing by namespace, the
tron_signTransaction payload, and returning the { raw_data_hex, signature } object — is the same in both integrations.Requirements
Object results indata require these minimum SDK versions:
Earlier versions type the confirm results as strings only and cannot carry the Tron result object.
Tron payment flow
A Tron payment follows the same three-call flow as any other WalletConnect Pay payment. The Tron-specific parts are the signing method (tron_signTransaction), the verification your wallet performs before signing, the object it returns, and the asynchronous settlement.
Key differences from other chains
- Sign-only relay —
raw_data_hexis opaque. Refreshing the expiration, re-deriving the TAPOS reference block, adjustingfee_limit, or re-encodingraw_dataall change the hash and get the payment rejected withtx_id_mismatch. - Object result — the confirm result is
{ raw_data_hex, signature }, not a bare signature string. This is whyconfirmPaymenttakesdatarather thansignatures. - The buyer pays energy — there is no fee payer and no fee bump on Tron. WalletConnect Pay offers a Tron option only to accounts holding USDT and enough TRX for energy (currently 14 TRX). An unfunded account is not offered Tron at all.
- Mainnet only — WalletConnect Pay settles Tron on mainnet (
tron:0x2b6653dc). - Settlement takes a few seconds — the gateway broadcasts the transaction and waits for inclusion.
confirmPaymentkeeps polling and resolves withsucceededorfailed, exactly as on other chains; nothing extra to handle.
Implementation requirements
Advertise Tron accounts
Include the wallet’s Tron mainnet account when callinggetPaymentOptions, using the CAIP-10 format:
- TypeScript
- Kotlin
- Swift
- Dart
accounts.ts
Only advertise a Tron account if your wallet holds Tron keys. The gateway checks the account’s USDT and TRX balances and omits the Tron option when either is insufficient — this is expected, not an integration error.
Route actions by namespace
Extract the namespace fromactions[i].walletRpc.chainId and route tron actions to the Tron signer:
- TypeScript
- Kotlin
- Swift
- Dart
routeActions.ts
Parse the tron_signTransaction action
The action’s params is a JSON string. It may be array-wrapped, and the transaction may be nested once more under transaction — accept both shapes, exactly as the WalletConnect Sign tron_signTransaction request handler does:
params.json
parseTronAction.ts
Verify before signing
Verify the payload before asking the user to approve, so a bad payload surfaces as a readable wallet-side error instead of an opaque gateway rejection at confirm:txIDmust equalsha256(raw_data_hex)— anything else means the bytes were altered and the gateway would reject the payment withtx_id_mismatch.- The transaction owner must be the quoted buyer —
raw_data.contract[0].parameter.value.owner_addressmust match the account the option was quoted against, or the gateway rejects withowner_mismatch.
Sign the digest verbatim
Signsha256(raw_data_hex) with the account’s secp256k1 key and return the 65-byte recoverable signature (r ‖ s ‖ v) as 130 hex characters. Do not pass the transaction through a helper that re-serializes raw_data from JSON (such as TronWeb’s trx.sign) — it can change the bytes and therefore the hash.
- TypeScript
- Kotlin
- Swift
- Dart
handleTronAction.ts
Do not broadcast
Do not implementtron_sendTransaction for Pay flows and do not call sendRawTransaction. WalletConnect Pay broadcasts the signed transaction; a wallet that also broadcasts causes a duplicate submission.
Complete action handler
- TypeScript
- Kotlin
- Swift
- Dart
approvePayment.ts
Validate your integration
1
Funded Tron account
Import a mainnet account holding USDT and at least 14 TRX. Open a payment link whose merchant accepts USDT on Tron and verify that:
- The Tron option is presented
- The wallet verifies
txIDand the owner, then signs - The confirm request carries
{ raw_data_hex, signature }as an object indata confirmPaymentresolves withsucceededand the transaction appears in a Tron explorer
2
Tampered payload
Alter one byte of
raw_data_hex in a test harness and verify the wallet fails with a txID mismatch before signing, rather than at confirm.3
Regression on other chains
Confirm that EVM and Solana payments still work — their results stay plain strings in the same
data array.Sample implementations
React Native
wallets/rn_cli_wallet — see TronLib.signPaymentTransaction for the verification and signing, PaymentStore.approvePayment for the tron route, and usePairing for advertising the Tron mainnet account.Web
advanced/wallets/react-wallet-v2 — see TronLib.signPaymentTransaction and the tron_signTransaction branch in PaymentStore.