-
Notifications
You must be signed in to change notification settings - Fork 236
TIP-6963: Multi Injected Provider Discovery #737
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Labels
enhancement
New feature or request
Comments
感觉 这个提案 已经很成熟了, 希望尽快落地,最好 能有个 页面 追踪 钱包和登陆库( tronwallet-adapter 等)的进度 |
能加一个demo 的js么,包括钱包和dapp的具体实现TIP6963 |
The following code snippet shows how to implement this protocol: import { TronWeb } from "tronweb";
interface RequestArguments {
readonly method: string;
readonly params?: unknown[] | object;
}
interface TIP1193Provider {
request: (args: RequestArguments) => Promise<unknown>;
on(event: string, listener: (...args: any[]) => void): this;
removeListener(event: string, listener: (...args: any[]) => void): this;
tronWeb: TronWeb;
[key: `is${string}`]: boolean;
}
/**
* Represents the assets needed to display a wallet
*/
interface TIP6963ProviderInfo {
uuid: string;
name: string;
icon: string;
rdns: string;
}
interface TIP6963ProviderDetail {
info: TIP6963ProviderInfo;
provider: TIP1193Provider;
}
// Announce Event dispatched by a Wallet
interface TIP6963AnnounceProviderEvent extends CustomEvent {
type: "TIP6963:announceProvider";
detail: TIP6963ProviderDetail;
}
// Request Event dispatched by a DApp
interface TIP6963RequestProviderEvent extends Event {
type: "TIP6963:requestProvider";
}
// Wallet:
const info: TIP6963ProviderInfo = {
uuid: 'generated uuid v4',
name: "TIP6963 Wallet",
icon: 'your wallet icon',
rdns: "com.tip1193.wallet",
};
const provider: TIP1193Provider = {
// Your wallet TRON provider
request: () => {
return new Promise((resolve, reject) => {
// Your wallet TRON provider logic
});
},
on() {
return this;
},
removeListener() {
return this;
},
tronWeb: new TronWeb()
};
const announceEvent: TIP6963AnnounceProviderEvent = new CustomEvent(
"TIP6963:announceProvider",
{ detail: Object.freeze({ info, provider }) }
);
// The Wallet dispatches an announce event which is heard by
// the DApp code that had run earlier
window.dispatchEvent(announceEvent);
// The Wallet listens to the request events which may be
// dispatched later and re-dispatches the `TIP6963AnnounceProviderEvent`
window.addEventListener("TIP6963:requestProvider", () => {
window.dispatchEvent(announceEvent);
});
// Dapp:
// The DApp listens to announced providers
window.addEventListener(
"TIP6963:announceProvider",
(event: TIP6963AnnounceProviderEvent) => {
// Here we can store the provider and use it later
}
);
// The DApp dispatches a request event which will be heard by
// Wallets' code that had run earlier
window.dispatchEvent(new Event("TIP6963:requestProvider")); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Table of Contents
Summary
This protocol specifies an alternative discovery mechanism to
window.tron
for TIP-1193 providers which supports discovering multiple injected Wallet Providers in a web page using Javascript’swindow
events.Abstract
Currently, Tron wallets is recommended to inject their Wallet providers into the same window object
window.tron
according to TIP-1193. However, this creates conflicts for users that may install more than one browser extension.Browser extensions are loaded in the web page in an unpredictable order and the final Provider is usually provided by the last wallet resulting in that users cannot select the specified wallet if the wallet is not loaded last.
This results not only in a degraded user experience but also increases the barrier to entry for new browser extensions as users are forced to only install one browser extension at a time.
In this proposal, we present a solution that focuses on optimizing the interoperability of multiple Wallet Providers. This solution aims to foster fairer competition by reducing the barriers to entry for new Wallet Providers, along with enhancing the user experience on Tron networks.
This is achieved by introducing a set of window events to provide a two-way communication protocol between Tron libraries and injected scripts provided by browser extensions thus enabling users to select their wallet of choice.
Specification
Definitions
Wallet Provider: A user agent that manages keys and facilitates transactions with Tron.
Decentralized Application (DApp): A web page that relies upon one or many Web3 platform APIs which are exposed to the web page via the Wallet.
Provider Discovery Library: A library or piece of software that assists a DApp to interact with the Wallet.
Provider Info
Each Wallet Provider will be announced with the following interface
TIP6963ProviderInfo
. The values in theTIP6963ProviderInfo
must be included within theTIP6963ProviderInfo
object. TheTIP6963ProviderInfo
may also include extra extensible properties within the object. If a DApp does not recognize the additional properties, it should ignore them.uuid
- a globally unique identifier the Wallet Provider that must be (UUIDv4 compliant) to uniquely distinguish different TIP-1193 provider sessions that have matching properties defined below during the lifetime of the page. The cryptographic uniqueness provided by UUIDv4 guarantees that two independentTIP6963ProviderInfo
objects can be separately identified.name
- a human-readable local alias of the Wallet Provider to be displayed to the user on the DApp. (e.g.Example Wallet Extension
orAwesome Example Wallet
)icon
- a URI pointing to an image. The image should be a square with 96x96px minimum resolution. See the Images/Icons below for further requirements of this property.rdns
- The Wallet must supply therdns
property which is intended to be a domain name from the Domain Name System in reverse syntax ordering such ascom.example.subdomain
. It's up to the Wallet to determine the domain name they wish to use, but it's generally expected the identifier will remain the same throughout the development of the Wallet. It's also worth noting that similar to a user agent string in browsers, there are times where the supplied value could be unknown, invalid, incorrect, or attempt to imitate a different Wallet. Therefore, the DApp should be able to handle these failure cases with minimal degradation to the functionality of the DApp.Images/Icons
A URI-encoded image was chosen to enable flexibility for multiple protocols for fetching and rendering icons, for example:
The
icon
string must be a data URI as defined in RFC-2397. The image should be a square with 96x96px minimum resolution. The image format is recommended to be either lossless or vector based such as PNG, WebP or SVG to make the image easy to render on the DApp. Since SVG images can execute Javascript, applications and libraries must render SVG images using the<img>
tag to ensure no untrusted Javascript execution can occur.RDNS
The
rdns
(Reverse-DNS) property serves to provide an identifier which DApps can rely on to be stable between sessions. The Reverse Domain Name Notation is chosen to prevent namespace collisions.The Reverse-DNS convention implies that the value should start with a reversed DNS domain name controlled by the Provider. The domain name should be followed by a subdomain or a product name. Example:
com.example.MyBrowserWallet
.rdns
value must be a valid RFC-1034 Domain Name;rdns
value should be an active domain controlled by the Provider;rnds
value for feature detection as these are self-attested and prone to impersonation or bad incentives without an additional verification mechanism; feature-discovery and verification are both out of scope of this interface specification.Provider Detail
The
TIP6963ProviderDetail
is used as a composition interface to announce a Wallet Provider and related metadata about the Wallet Provider. TheTIP6963ProviderDetail
must contain aninfo
property of typeTIP6963ProviderInfo
and aprovider
property of typeTIP1193Provider
defined by TIP-1193.Window Events
In order to prevent provider collisions, the DApp and the Wallet are expected to emit an event and instantiate an eventListener to discover the various Wallets. This forms an Event concurrency loop.
Since the DApp code and Wallet code aren't guaranteed to run in a particular order, the events are designed to handle such race conditions.
To emit events, both DApps and Wallets must use the
window.dispatchEvent
function to emit events and must use thewindow.addEventListener
function to observe events. There are two Event interfaces used for the DApp and Wallet to discover each other.Announce and Request Events
The
TIP6963AnnounceProviderEvent
interface must be aCustomEvent
object with atype
property containing a string value ofTIP6963:announceProvider
and adetail
property with an object value of typeTIP6963ProviderDetail
. TheTIP6963ProviderDetail
object should be frozen by callingObject.freeze()
on the value of thedetail
property.The
TIP6963RequestProviderEvent
interface must be anEvent
object with atype
property containing a string value ofTIP6963:requestProvider
.The Wallet must announce the
TIP6963AnnounceProviderEvent
to the DApp via awindow.dispatchEvent()
function call. The Wallet must add an EventListener to catch anTIP6963RequestProviderEvent
dispatched from the DApp. This EventListener must use a handler that will re-dispatch anTIP6963AnnounceProviderEvent
. This re-announcement by the Wallet is useful for when a Wallet's initial Event announcement may have been delayed or fired before the DApp had initialized its EventListener. This allows the various Wallet Providers to react to the DApp without the need to pollute thewindow.tron
namespace which can produce non-deterministic wallet behavior such as different wallets connecting each time.The Wallet dispatches the
"TIP6963:announceProvider"
event with immutable contents and listens to the"TIP6963:requestProvider"
event:The DApp must listen for the
TIP6963AnnounceProviderEvent
dispatched by the Wallet via awindow.addEventListener()
method and must not remove the Event Listener for the lifetime of the page so that the DApp can continue to handle Events beyond the initial page load interaction. The DApp must dispatch theTIP6963RequestProviderEvent
via awindow.dispatchEvent()
function call after theTIP6963AnnounceProviderEvent
handler has been initialized.The DApp may elect to persist various
TIP6963ProviderDetail
objects contained in the announcement events sent by multiple wallets. Thus, if the user wishes to utilize a different Wallet over time, the user can express this within the DApp's interface and the DApp can immediately elect to send transactions to that new Wallet. Otherwise, the DApp may re-initiate the wallet discovery flow via dispatching a newTIP6963RequestProviderEvent
, potentially discovering a different set of wallets.The described orchestration of events guarantees that the DApp is able to discover the Wallet, regardless of which code executes first, the Wallet code or the DApp code.
Backwards Compatibility
This TIP doesn't require supplanting
window.tron
, so it doesn't directly break existing applications that cannot update to this method of Wallet discovery. However, it is recommended DApps implement this TIP to ensure discovery of multiple Wallet Providers and should disablewindow.tron
usage except as a fail-over when discovery fails. Similarly, Wallets should keep compatibility ofwindow.tron
to ensure backwards compatibility for DApps that have not implemented this TIP. In order to prevent the previous issues of namespace collisions, it's also recommended that wallets inject their provider object under a wallet specific namespace then proxy the object into thewindow.tron
namespace.The text was updated successfully, but these errors were encountered: