TIP-1193/1474: Standard JSON-RPC and Provider Specification for TRON

TIP-1193/1474: Standard JSON-RPC and Provider Specification for TRON

Summary

Establish a unified standard for how TRON wallets (providers) and TRON nodes communicate with decentralized applications (dApps). This proposal defines a consistent JSON-RPC API for TRON nodes and a standard provider interface for wallets, aligning with TRON’s unique architecture (TVM, resource model, address format) while leveraging lessons from Ethereum’s provider and JSON-RPC standards where sensible. The goal is to improve interoperability and developer experience by standardizing method names, events, error codes, and behaviors across the TRON ecosystem.

Abstract

TRON Improvement Proposal (TIP) – “Standard JSON-RPC and Provider Specification for TRON” defines a common protocol for dApps to interact with TRON wallets and nodes. It standardizes the JSON-RPC methods exposed by TRON full nodes and the JavaScript provider interface injected by wallets, ensuring they reflect TRON’s specifics such as the Tron Virtual Machine (TVM), resource model (Bandwidth & Energy), TRON address formats, and TRON-specific transactions and events. While inspired by Ethereum’s JSON-RPC (e.g. eth_call, eth_getBalance) and provider API standards (e.g. EIP-1193, EIP-1102), this specification adapts them to TRON’s design. It introduces required methods for account access, transaction signing, network switching, and resource queries, a unified event system (for account or network changes), and a clear error handling scheme consistent with industry standards. By implementing this standard, all TRON wallets and nodes will behave uniformly, reducing DApp development friction and ensuring compatibility across the TRON ecosystem.

Motivation

Currently, TRON lacks a single standardized interface for DApps to connect with wallets and nodes. Different wallets (e.g. TronLink, Ledger, WalletConnect-Tron) have had varying APIs (e.g. TronLink injects window.tronLink with custom methods), and TRON node access can be done via Ethereum-compatible JSON-RPC or via TRON-specific REST endpoints. This inconsistency causes increased development workload and integration complexity. Key issues include:

  • Without a standard provider API, DApp developers must write custom logic for each TRON wallet. For example, TronLink uses tronLink.request({ method: 'tron_requestAccounts' }) while other wallets or future wallets might differ. A unified provider spec (analogous to Ethereum’s provider standard) is needed so DApps can easily support any TRON wallet with minimal changes.
  • TRON nodes support many Ethereum JSON-RPC methods, but some Ethereum methods are not applicable to TRON and TRON adds unique transaction APIs. Developers must juggle between Ethereum-like RPC calls (for chain queries) and TRON REST APIs (for account resource info or broadcasting transactions). This proposal standardizes the node RPC interface, filling gaps with TRON-specific methods, so DApps can use a single JSON-RPC workflow for all operations.
  • Ethereum-centric tools don’t account for TRON’s Bandwidth/Energy resource model and different transaction structure. Without a standard, DApps may not properly handle TRON’s fee limits, resource consumption, or address formats. We need to expose TRON-specific concepts (energy limits, bandwidth points, etc.) through standardized RPC calls and provider methods to fully support TRON’s architecture.
  • In the past, TRON DApps sometimes automatically accessed user accounts on page load. Following Ethereum’s EIP-1102, TRON should enforce an opt-in model for account access. A standard provider spec can mandate that wallets do not expose accounts or perform transactions without explicit user approval, enhancing user privacy and security.

By addressing these issues with a cohesive specification, we aim to make TRON DApp development more straightforward and secure. All wallets implementing this spec will be interoperable, and DApps can rely on uniform behaviors for fundamental operations (connecting, signing, querying), thus accelerating TRON’s ecosystem growth.

Specification

This specification defines two complementary components required for consistent interaction between decentralized applications and the TRON blockchain. The first component is the TRON Provider Interface, a JavaScript API injected by TRON-compatible wallets into web or mobile environments, enabling account authorization, message signing, transaction handling, and network management. The second component is the TRON JSON-RPC Standard, which unifies the RPC methods exposed by TRON Full Nodes. Both parts together create a predictable environment for wallet developers, DApp builders, and infrastructure providers.

1. Provider Interface (Wallet ↔ DApp)

Global Provider Object

TRON wallets must inject a global provider instance into the execution context of the DApp (commonly window.tron). Although many existing wallets still expose branded objects (e.g., window.tronLink), the unified provider interface must remain accessible under a standardized property name. DApps should treat this provider as the authoritative gateway to TRON-related capabilities, relying on it for permissions and account-level operations.

Provider request() Method

The provider exposes a single asynchronous entry point:

tron.request({ method, params })

This pattern mirrors Ethereum’s EIP-1193 and is intentionally designed for maximum compatibility with cross-chain tooling. All account access, signing workflows, and transaction dispatches flow through this method. Providers may implement additional private or convenience APIs, but DApps should rely only on the methods defined in this specification.

Account Access and Identity

eth_requestAccounts prompts the user to authorize access to one or more TRON accounts. It must return Base58Check addresses (T-prefix). Rejection must raise error code 4001. Providers should transparently convert between base58 and TRON’s hex format (0x41…) depending on where the address is consumed.

eth_accounts returns accounts previously authorized by the user. While optional, it is recommended for compatibility with widely used Web3 libraries.

Providers must consistently expose user-facing addresses in base58 format but accept both formats as input. Internally, wallet-to-node communication uses 0x-prefixed hex.

Chain and Network Management

eth_chainId returns the chain ID for the connected TRON network.
net_version provides a legacy identifier.
wallet_switchEthereumChain enables programmatic network switches initiated by the DApp.
wallet_addEthereumChain may be implemented for adding testnets or private TRON networks.

When the network changes, the provider must emit a chainChanged event and update all dependent states. The provider must not silently switch networks without either explicit user action or an explicit DApp request.

Transaction Handling

eth_sendTransaction is used to build, sign, and broadcast TRON transactions, even though its field names originate from Ethereum. The provider must interpret from, to, value, data, and gas in TRON’s execution model. Transaction objects must be transformed into either a native transfer or a smart contract invocation, and TRON-specific metadata such as block references and fee limits must be added automatically. After user confirmation, the wallet signs the transaction and broadcasts it through the node’s raw-transaction endpoint.

Message signing via eth_sign or personal_sign must apply TRON’s standard message prefixing (TIP-104). Signatures are returned in 65-byte r|s|v format for compatibility with existing cryptographic tooling.

Events

Providers must implement a standard event interface to allow DApps to react dynamically to wallet state changes. Required events include:

  • accountsChanged — emitted when the active user account changes
  • chainChanged — emitted when the network changes
  • connect — triggered when wallet establishes a valid RPC connection
  • disconnect — triggered when the wallet is locked or the connection is lost

These events bring TRON provider behavior in line with Ethereum EIP-1193, making cross-chain application logic more predictable.

Error Handling

All provider methods must use standardized JSON-RPC/EIP-1193 error codes. Common cases include user rejection (4001), unauthorized access (4100), unsupported method (4200), malformed parameters (-32602), and pending requests (-32002). DApps must be able to rely on consistent error structures to implement robust workflows.

2. JSON-RPC API (DApp/Wallet ↔ Node)

TRON Full Nodes aim to offer a high degree of Ethereum compatibility while preserving TRON-specific execution semantics (Energy/Bandwidth, DPoS finality, no nonce-based ordering). A unified JSON-RPC interface enables wallets, SDKs, and backend services to interact with nodes without requiring TRON-specific branching logic in most cases.

Core Blockchain Methods

Nodes must implement key Ethereum-compatible RPC calls:

  • eth_blockNumber, eth_getBlockByNumber, eth_getBlockByHash
    Blocks are formatted similarly to Ethereum blocks, with TRON-specific fields omitted or nullified where inapplicable (e.g., miner, difficulty).
  • eth_getTransactionByHash
    Exposes Ethereum-style translation of TRON transaction data.
  • eth_getTransactionReceipt
    Includes logs, status, bloom filters, and TRON extensions such as energyUsed, bandwidthUsed, and fee.
  • eth_getBalance returns TRX balance in SUN (hex).
  • eth_call executes read-only contract calls through TRON’s constant-call engine.
  • eth_estimateGas approximates required Energy for a contract execution.
  • eth_getCode, eth_getStorageAt expose on-chain bytecode and storage.
  • eth_getTransactionCount returns either the number of outgoing transactions or 0x0 because TRON does not use Ethereum-style nonces.
  • eth_gasPrice should return "0x0" because TRON has no dynamic gas price market.

Logs and Filters

Nodes must support eth_getLogs, returning event logs emitted by TRON smart contracts. Optional support for filter-based subscriptions (eth_newFilter, eth_getFilterChanges, etc.) increases compatibility with Ethereum tooling and is encouraged.

Network and Utility Methods

Standard RPC calls such as net_version, net_peerCount, web3_clientVersion, and web3_sha3 ensure consistent behavior across node implementations and allow DApps to perform environment checks or diagnostics.

TRON-Specific JSON-RPC Extensions

To expose functionality unique to TRON, additional namespaced methods are defined:

  • tron_getAccountResource(address) – Returns Energy and Bandwidth allocations, usage metrics, and other resource-related parameters needed for understanding transaction feasibility.

  • tron_getChainParameters() – Returns dynamic protocol parameters including energy fee rate, free bandwidth limits, and global resource constraints.

  • tron_getTokenBalance(address, tokenIdentifier) – Provides a unified interface for retrieving TRC-10 and TRC-20 balances without requiring the DApp to construct contract calls manually.

  • tron_broadcastTransaction(signedTx) – Broadcasts a raw signed transaction, mirroring eth_sendRawTransaction but allowing TRON-specific formatting flexibility.

  • tron_getTransactionInfoById(txHash) – Returns extended execution details not captured by Ethereum-style receipts, such as internal transactions and detailed result codes.

Nodes may accept either base58 or hex addresses as input but should return addresses in predictable, standard formats.

Example JSON-RPC Workflows:

  1. Get TRX Balance of an Account:
    Request:
{"jsonrpc":"2.0","id":1,"method":"eth_getBalance","params":["TABC...123", "latest"]}

(The address can also be given as "0x41<...>"; the node should handle conversion.)
Response:

{"jsonrpc":"2.0","id":1,"result":"0x8ac7230489e80000"}

This result, 0x8ac7230489e80000, corresponds to 10^20 sun (100,000 TRX) for example. The DApp would convert from hex to decimal as needed.
2. Call a TRC-20 Token Contract (balanceOf):
Request:

{
  "jsonrpc":"2.0","id":2,"method":"eth_call",
  "params": [{
     "to": "TTokenContractAddr...",
     "data": "0x70a08231000000000000000000000000" + "<address_without_0x41_prefix>"
  }, "latest"]
}
  • Here data is the function selector for balanceOf(address) (0x70a08231) plus 32-byte address (if the address is base58, the DApp must convert it to hex and remove the leading 0x41 for the 20-byte payload).
    Response:
{"jsonrpc":"2.0","id":2,"result":"0x0000000000000000000000000000000000000000000000056bc75e2d63100000"}

This hex is the 32-byte value representing the token balance (in this case 100 token units, depending on token decimals). The DApp would decode it.(If using the tron_getTokenBalance extension, the DApp could simplify the above by:

{"jsonrpc":"2.0","id":3,"method":"tron_getTokenBalance","params":["TUserAddr...", "TTokenContractAddr..."]}

and the node would directly return the balance hex or a number.)
3. Broadcast a Signed Transaction:
Suppose the DApp obtained a signed transaction (or the wallet, acting as a DApp client, is broadcasting).
Request:

{"jsonrpc":"2.0","id":3,"method":"eth_sendRawTransaction","params":["0x{signed_tx_hex}"]}

Response:

{"jsonrpc":"2.0","id":3,"result":"<txHash>"}

If the transaction was rejected (e.g. too low fee limit), an error:

{
  "jsonrpc":"2.0","id":3,
  "error": {"code": -32000, "message": "Energy limit too low for execution"}
}

(Exact message may vary; -32000 is a generic server error range per EIP-1474.

Compatibility and Omissions: Some Ethereum JSON-RPC methods are not applicable to TRON and should not be implemented or should return an explicit error (-32601 Method not found or 4200 unsupported):

  • Mining related calls (eth_coinbase, eth_hashrate, eth_mining, eth_submitWork): TRON is not a PoW chain, so these are not applicable.
  • Uncle/Auxiliary block calls (eth_getUncleByBlock..., eth_getUncleCount...): TRON has no uncle blocks, return error or empty.
  • eth_signTypedData: If TRON decides to support EIP-712 style typed data signing (perhaps via TIP-191 which might define a standard for signed data), it could be added. At present, not defined, so providers can treat it as unsupported or implement if needed using Tron’s domain separator rules.
  • personal_* methods beyond personal_sign: (like personal_newAccount, etc.) – account management is outside the scope of node JSON-RPC for TRON (wallets handle that offline).

All JSON-RPC methods must adhere to the hex encoding rules for quantities and data: quantities are hex without leading zeros (except zero which is “0x0”), and data (byte arrays) are 0x-prefixed even-length hex strings. The TRON node’s JSON-RPC will enforce these formats in responses.

Backwards Compatibility

This standard does not break existing TRON DApps or wallets—instead, it offers a path to unify them:

  • Wallets: TronLink and others may continue exposing their current objects (like window.tronLink), but must also support the standardized window.tron.request(...). Supporting both tron_requestAccounts and eth_requestAccounts is recommended during the transition. Event names like accountsChanged should be implemented natively, with optional legacy message fallbacks for compatibility.
  • DApps: Apps using TronLink or TronWeb will mostly continue to work. TronWeb can update its internals to use the new provider interface. Transitioning from custom methods to tron.request should be straightforward.
  • JSON-RPC Clients: Libraries like web3.js, ethers.js, and services like QuickNode already partially support TRON’s RPC. This spec adds tron_* methods without changing existing eth_* methods, so compatibility is preserved.
  • Tron REST API: The existing /wallet and /walletsolidity REST endpoints remain available. This TIP does not deprecate REST APIs, but encourages gradual migration to JSON-RPC.

It is recommended that all TRON wallets and node providers implement this proposal. However, to avoid disruption, a phased adoption is suggested:

  • Phase 1: Wallets implement request and standard events in addition to legacy API; Nodes implement any missing eth_* methods and Tron-specific ones.
  • Phase 2: DApps update to use the unified interface (possibly via updated TronWeb SDK that hides differences).
  • Phase 3: Eventually, legacy methods (tron_requestAccounts, etc.) can be deprecated once DApps have migrated, though wallets might never need to fully remove them to maintain compatibility.

Conclusion

In summary, this proposal establishes a unified, TRON-native standard for wallet provider interfaces and JSON-RPC node APIs, purpose-built for the architecture and resource model of the TRON blockchain. By aligning wallet behavior, method naming, error handling, and node responses under a common spec—without imposing Ethereum’s architecture—this standard empowers DApps, wallets, SDKs, and node providers to interoperate predictably and securely.

Through well-defined provider methods like eth_requestAccounts and eth_sendTransaction, consistent events such as accountsChanged, and a robust set of TRON-optimized JSON-RPC endpoints (including energy-aware transaction flows and direct access to TVM-specific features), the standard reduces integration overhead, prevents fragmentation, and accelerates development velocity across the TRON ecosystem.

We invite TRON wallet developers, infrastructure providers, and DApp teams to adopt and implement this specification. With broad community support, this standard can serve as the default interface layer for next-generation TRON applications—spanning DeFi, payments, custody solutions, NFTs, and more.

By embracing a single, extensible protocol surface that reflects the unique strengths of TRON, we ensure a smoother onboarding experience for developers, a more secure user journey, and a more scalable future for the network’s expanding ecosystem.

4 Likes

Hey, the proposed method returns a flat object with all fee parameters. Would it make sense to nest TRON-specific data under a tron key (e.g. { tron: { energyFee, bandwidthLimit, ... } }) to reduce naming conflicts and make the response easier to parse in cross-chain tools?

Hi, @emmanuil!

Thanks for raising this — it’s a valid consideration.

That said, our current design choice to return a flat object aligns with standard Ethereum-style JSON-RPC conventions, where most responses are single-level key-value pairs. This makes parsing simpler and minimizes friction for frontend tools or SDKs that expect primitive fields directly on the root object. Flattened outputs are also friendlier to most existing libraries that deal with response decoding.

Another factor is consistency across TRON methods. If we introduce nesting in some methods like tron_getAccountResource, but not others such as eth_getBalance, it could lead to a fragmented developer experience. Developers may have to remember which responses are nested and which are flat, which goes against our goal of standardizing interfaces across the ecosystem.

That said, we’re open to adding support for both formats. One idea would be to allow an optional namespaced: true parameter in the request, which would enable the nested response explicitly. This way, tools that prefer a structured layout can opt into it, while existing tooling remains compatible with the default flat format.

Let us know if there are specific cross-chain tools you’re integrating with that would benefit from the nested format — we’re definitely open to evolving the spec to support both paths if there’s a clear use case :slight_smile:

Regarding the tron_chainId (or eth_chainId equivalent) — will this return the decimal or the hex value by default? I’ve seen some confusion in the past where different providers returned different formats, which breaks chain-switching logic.

This feels like an important step for ecosystem tooling and interoperability. I have a question about event subscriptions: in the current RPC draft, is there a standard way to subscribe to multiple event filters atomically (e.g., filter by contract address and event signature), or will users need to handle this via multiple separate subscriptions and merge results locally?

Nice to see efforts toward a standardized JSON‑RPC and provider API for TRON — should make tooling more consistent across wallets and apps.

Interesting proposal! One thing I’m curious about: how does this RPC spec handle cases where multiple providers are available? Specifically, is there a recommended strategy for clients to choose a fallback provider, or is that left entirely to implementers?

Good write‑up! On the security side, is there any guidance on how providers should handle malformed queries or rate‑limiting? For public RPC endpoints, best practices around throttling, request validation, and error formats make a big difference for clients trying to build resilient apps.