tip: 1193
title: TRON Provider JavaScript API
author: Aaron <[email protected]>
discussions to: https://github.com/tronprotocol/tips/issues/466
category: Interface
status: Final
created: 2022-09-26
This protocol specifies a JavaScript TRON provider, it is used to ensure the consistency of interaction between TRON wallets and TRON DApps.
A common convention in the TRON web application (“DApp”) ecosystem is that the key management software ("wallets") exposes their API via a JavaScript object on the web page. This object is called “the Provider”.
This protocol normalizes the TRON provider's API and is designed to be event-driven, independent of the call method. The Provider can be easily extended by defining new methods and event types.
This protocol recommends using window.tron
as the Provider.
Historically, some TRON wallets provide tronWeb object, and this protocol recommends that the Provider will still provide tronWeb object to avoid additional compatible development of TRON DApps for the Provider of this protocol.
The Provider must implement and expose the API and property defined in this section. All API and property entities must adhere to the types and interfaces defined in this section.
tron.request({
method: 'requestMethod',
params: ['param1', 'param2'],
})
interface RequestArguments {
readonly method: string;
readonly params?: unknown[] | object;
}
- The Provider must identify the requested method by the value of
RequestArguments.method
. - If the requested method takes any parameters, the Provider must accept them as the value of
RequestArguments.params
.
tron.request
must be handled such that the returned Promise either resolves with a value per the requested method’s specification, or rejects with an error.- If resolved, the Promise must resolve with a result per the method’s specification, unless the method’s return type is particularly defined.
- If the returned Promise rejects, it must reject as specified in the Error Code section below.
- The returned Promise must reject if any of the following conditions are met:
- An error is returned for the request.
- The Provider encounters an error or fails to process the request for any reason.
- The returned Promise should reject if any of the following conditions are met:
- The Provider is disconnected. If rejecting for this reason, the Promise rejection error code must be
4900
. - The
tron.request
request is directed at a specific chain, and the Provider is not connected to that chain, but is connected to at least one other chain. If rejecting for this reason, the Promise rejection error code must be4901
. - The Provider does not support the
method
intron.request
request. If rejecting for this reason, the Promise rejection error code must be4200
.
- The Provider is disconnected. If rejecting for this reason, the Promise rejection error code must be
The structure that returns the error is as follows:
interface ProviderRpcError extends Error {
code: number;
message: string;
data?: unknown;
}
message
- must be a human-readable string
- Should be the
message
of the Provider Error section, or themessage
in the method's specification
code
- must be an integer number
- Should be the
code
of the Provider Error section, or thecode
in the method's specification
data
- should contain any other useful information about the error
code | message | Description |
---|---|---|
4001 | User Rejected Request | The user rejected the request. |
4100 | Unauthorized | The requested method and/or account has not been authorized by the user. |
4200 | Unsupported Method | The Provider does not support the requested method. |
4900 | Disconnected | The Provider is disconnected from all chains. |
4901 | Chain Disconnected | The Provider is not connected to the requested chain. |
wallet needs to import tronWeb library, instantiate tronWeb, The Provider provides instantiated tronWeb for DApps.
const tronWeb = tron.tronWeb;
tron.tronWeb
needs to meet the following requirements:
- When the wallet changes the currently connected chain, it must reinitialize tronWeb and update
tron.tronWeb
This is a non-normative property, but wallet implementation is recommended.
In actual development, the DApp may need to determine what wallet is currently providing the Provider, so as to facilitate the compatible development of different wallets by the DApp.
For example: isTronLink
, isTokenPocket
, isTrustWallet
, etc.
This protocol does not limit the specific property name, nor does it require the implementation of this property.
const isTronLink = tron.isTronLink as boolean;
The Provider must implement the following event handling methods:
on
removeListener
These methods must be implemented according toNode.js EventEmitter API.
If the Provider becomes connected, the Provider must emit the event named connect
.
This includes when:
- The Provider first connects to a chain after initialization.
- The Provider connects to a chain after the
disconnect
event was emitted. This event must be emitted with an object of the following form:
interface ProviderConnectInfo {
readonly chainId: string;
}
- The chainId must be obtained through the RPC method of TRON's
eth_chainId
.
tron.on('connect', (connectInfo: ProviderConnectInfo) => {
console.log(connectInfo); // example: {chainId: '0x2b6653dc' }
})
If the Provider becomes disconnected from all chains, the Provider must emit the event named disconnect with value error: ProviderRpcError
object according to the Provider Error specification.
tron.on('disconnect', (providerRpcError: ProviderRpcError) => {
console.error(connectInfo); // example: { code: 4900, message: 'Disconnected' }
})
If the chain to which the Provider is connected changes, the Provider must emit a chainChanged
event and emit an object of type ProviderConnectInfo
that explicitly informs the new chainId value.
tron.on('chainChanged', (connectInfo: ProviderConnectInfo) => {
console.log(connectInfo); // example: {chainId: '0x2b6653dc' }
})
If the Provider's current account changes, the Provider must emit the accountsChanged
event and the currently available account address in the form of accounts: string[]
.
tron.on('accountsChanged', (accounts: string[]) => {
console.log(accounts); // example: ['TQKLs3GzCNLjzyCvaPWSrqcpUGUhadxm7P']
})
The Provider is intended to pass messages between a TRON wallet and a TRON DApps. It is not responsible for private key or account management; it merely processes messages and emits events. Consequently, account security and user privacy need to be implemented in middleware between the Provider and its TRON wallet. The Provider can be thought of as an extension of the wallet, exposed in an untrusted environment, under the control of some third party.
Since the Provider is a JavaScript object, consumers can generally perform arbitrary operations on the Provider, and all its properties can be read or overwritten. Therefore, it is best to treat the Provider object as though it is controlled by an adversary. It is paramount that the Provider implementer protects the user, wallet by ensuring that:
- The Provider does not contain any private user data.
- The Provider and wallet programs are isolated from each other.
- Set a limit for the Provider's request rate to the wallet.
- The wallet validates all data sent from the Provider.
Before this protocol was finalized, some wallets implemented non-normative versions. In order to be compatible with the historical DApps, the wallets can be compatible with non-normative versions on the premise of implementing this protocol.