Skip to content

Latest commit

 

History

History
199 lines (194 loc) · 9.42 KB

tip-1193.md

File metadata and controls

199 lines (194 loc) · 9.42 KB
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

Table of Contents

Summary

This protocol specifies a JavaScript TRON provider, it is used to ensure the consistency of interaction between TRON wallets and TRON DApps.

Abstract

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. ​ ​

Specification

API

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. ​

API: request

Example
tron.request({
  method: 'requestMethod',
  params: ['param1', 'param2'],
})

Parameters
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. ​
Returns
  • 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 be 4901.
    • The Provider does not support the method in tron.request request. If rejecting for this reason, the Promise rejection error code must be 4200.
Error Code

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 the message in the method's specification
  • code
    • must be an integer number
    • Should be the code of the Provider Error section, or the code in the method's specification
  • data
    • should contain any other useful information about the error ​ ​
Provider 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.

Property

Property: tronWeb

wallet needs to import tronWeb library, instantiate tronWeb, The Provider provides instantiated tronWeb for DApps.

Example
const tronWeb = tron.tronWeb;
Constraints

tron.tronWeb needs to meet the following requirements:

  • When the wallet changes the currently connected chain, it must reinitialize tronWeb and update tron.tronWeb

Property: is[WalletName]

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.

Example
const isTronLink = tron.isTronLink as boolean;

Events

The Provider must implement the following event handling methods:

  • on
  • removeListener

These methods must be implemented according toNode.js EventEmitter API. ​

Event: connect

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.
Example
tron.on('connect', (connectInfo: ProviderConnectInfo) => {
  console.log(connectInfo); // example: {chainId: '0x2b6653dc' }
})

Event: disconnect

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.

Example
tron.on('disconnect', (providerRpcError: ProviderRpcError) => {
  console.error(connectInfo); // example: { code: 4900, message: 'Disconnected' }
})

Event: chainChanged

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.

Example
tron.on('chainChanged', (connectInfo: ProviderConnectInfo) => {
  console.log(connectInfo); // example: {chainId: '0x2b6653dc' }
})

Event: accountsChanged

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[].

Example
tron.on('accountsChanged', (accounts: string[]) => {
  console.log(accounts); // example: ['TQKLs3GzCNLjzyCvaPWSrqcpUGUhadxm7P']
})

Security Considerations

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.

Handling Adversarial Behavior

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.

Backwards compatibility

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.