Chaos When Wallets Are Summoned
Connecting a wallet is a crucial step in entering the Web3 world, and Web3 users often need to connect wallets on various DApp websites. However, this seemingly simple action can sometimes cause significant inconvenience to users.
Connecting Wallets
Imagine a scenario where a new Web3 user, out of curiosity, has installed several wallet plugins, visits a DApp website, and wishes to use their browser plugin wallet to connect to it. However, when they click on the “Connect Wallet” button provided by the website and select a wallet to use for connecting to the DApp, they may find that the popped-up wallet is not the one they selected. This can lead to confusion and panic, making them believe that their computer is infected with a virus and thus executing unexpected operations.
Blockchain wallets serve as crucial gateways to connecting with the blockchain, and in order to dominate this gateway, various wallets employ various methods. One of the most headache-inducing issues for DApp developers and users is the tampering of global variables by different wallets.
In the current logic of browser wallet implementations, exposing wallet functionality is done by injecting global variables into the browser (for example, Ethereum platform wallets inject their functions into “window.ethereum” so that DApps can interact with the wallet’s methods).
However, since many wallets inject themselves into the same window.ethereum variable, this results in later registered wallets overriding previous ones, ending up summoning only the most recently registered wallet.
Sometimes, DApp users must temporarily disable other wallet plugins or only install a particular wallet in order to use the wallet they desire. This is a far cry from the wallet developers’ initial intentions and even if a new wallet is superior, it is challenging to attract users who are already using other wallets.
Some may wonder why it is necessary to inject into the same variable. If there are two wallets, A and B, it would suffice for A to inject itself into “window.a” and B into “window.b”. By calling the corresponding object’s provided methods, one can avoid the problem of intending to summon A but instead summoning B. This method can indeed resolve competition issues. However, the problem lies in the fact that if a DApp is to support multiple wallet connections, developers must predefine all wallet names they want to adapt in the code and call the relevant wallet’s methods when a user selects a specific wallet. This makes code maintenance quite cumbersome. Injecting all wallets into the same object can save one from this hassle.
Solution
To break free from the aforementioned dilemma, there are two similar standards in the community.
Ethereum’s Solution: EIP-6963
The Ethereum community proposed the EIP-6963 proposal in May 2023.
The basic logic is simple: ditch global variables and instead use agreed-upon events to address wallet registration and discovery issues.
Specifically, after a plugin wallet successfully loads, it triggers a unified “eip6963:announceProvider” event to notify DApps of a new available wallet. DApps then listen for this event to know which wallets are currently available to them.
By avoiding the problems caused by directly using global variables through an abstract event listening logic, this method can automatically discover the wallets available in the user’s environment, resolving the dilemma.
Community Standard: Wallet Standard
EIP-6963 is an Ethereum ecosystem standard, but not just Ethereum, other chain platforms also face similar issues. For instance, wallets in the Solana chain commonly inject themselves into the “window.solana” variable, leading to competition scenarios.
Can the Solana ecosystem also implement this standard? While EIP-6963 is solely aimed at solving wallet discovery issues in the Ethereum ecosystem, the underlying idea can be applied to all chain platforms. Therefore, it is entirely feasible to provide a universal standard that enables wallet and DApp implementations across all blockchain platforms, allowing developers and users of all chain platforms to benefit from the convenience offered by EIP-6963. In theory, this is entirely possible, and some developers are already doing so, known as the Wallet Standard.
The core work of the Wallet Standard involves providing two functions: “registerWallet” and “getWallets”, the former for wallets and the latter for DApps.
Wallets call “registerWallet”, passing a wallet object encapsulating the wallet’s functionalities (e.g., the Connect method for connecting the wallet). Internally, the function triggers a RegisterWalletEvent event, where the event’s parameter is a callback function for DApps to call when the RegisterWalletEvent event is triggered. This callback function essentially passes the wallet object to the DApp, allowing the DApp to obtain a reference to the wallet object and interact with it.
DApp developers do not need to write code to listen for and receive wallet objects, as this functionality is already built into the Wallet Standard through “getWallets”. However, while getWallets listens for events, developers still need to consider how to handle these events. For instance, where should the obtained wallets be stored? Some wallets may load before the DApp, while others may load afterward, how should the states of these wallets be maintained? To address these detailed issues, the Wallet Standard also provides the “@wallet-standard/react” package, allowing developers to use React Hooks provided by it to access the desired data, including wallet lists, currently connected wallets, and wallet-provided methods.
Wallet Standard Features
In addition to the basic feature of obtaining wallet objects, the Wallet Standard also defines some standard Features.
In reality, wallets have some fundamental functionalities such as connecting and listening to wallet events. The Wallet Standard offers features like “standard:connect”, “standard:events”, etc. Once wallet providers implement these features, DApps can easily determine whether a wallet supports certain operations based on these values.
The “standard:*” mentioned above represents the internally defined features of the Wallet Standard. In fact, these values are not rigidly set, allowing for flexible extensions. Different chain platforms may have their unique features. For instance, Solana commonly agrees on “solana:*”. Common features in the Solana platform include “solana:signTransaction” and “solana:signMessage”.
Current Status of Wallet Standard
There are currently few projects that have implemented the Wallet Standard, with notable mentions being Solana and Sui.
In the Solana adapter of Ant Design Web3, support for automatically detecting wallets that conform to the Wallet Standard has been included. Developers only need to enable “autoAddRegisteredWallets” to experience this convenience without the need for configuring a plethora of wallet metadata, significantly enhancing the development and user experience.
The logic for connecting wallets on ZAN.TOP also faced similar issues in the early stages. However, thanks to the configuration provided by Ant Design Web3, adapting to the EIP-6963 standard was effortless. Users should already have experienced this when binding addresses at https://zan.top/personal/account?chInfo=ch_wxdyh.
Implementation Across Blockchain Ecosystems
Currently, different blockchain platforms have varying attitudes towards the Wallet Standard (or EIP-6963). Here are a few examples:
Bitcoin
Bitcoin does not currently have a similar standard in place. While there is a project that has implemented the Wallet Standard, it has not garnered much attention, and there have been no new code submissions for a while.
Developers currently have to manually maintain states or use some development packages for assistance. For instance, in the Bitcoin adapter implementation within Ant Design Web3, different wallets are fetched from various global variables and stored in a unified state. While this alleviates wallet conflict issues, the problem of not automatically sensing available wallets still persists.
Ethereum
The Ethereum platform has already adopted the EIP-6963 standard, with most related libraries and wallets providing support.
Solana
As mentioned earlier, the official implementation can be found at: https://github.com/solana-labs/wallet-standard
Sui
Sui has already implemented the Wallet Standard, and the methods for use can be found in the official documentation: https://docs.sui.io/standards/wallet-standard
Support from DApp Development Libraries
wagmi
wagmi has provided support for EIP-6963 through the mipd library (https://github.com/wevm/mipd). For specific methods, refer to the wagmi documentation.
RainbowKit
RainbowKit (https://www.rainbowkit.com/) is based on wagmi internally and has built-in support for EIP-6963.
Ant Design Web3
The Ethereum and Solana adapters of Ant Design Web3 (https://web3.ant.design/) offer excellent support for both standards, making it convenient for developers to enable them.
For Ethereum DApp developers, simply adding the eip6963 configuration is sufficient. Pay attention to lines 23-25 related to EIP-6963:
Similarly, if you are a DApp developer within the Solana ecosystem, the process is akin. It provides the autoAddRegisteredWallets property:
In Conclusion
EIP-6963 and the Wallet Standard significantly enhance the user experience of connecting wallets and reduce the barriers for new wallet providers to enter the market. Hopefully, in the future, more chain platforms, wallets, and DApp developers can provide or implement related standards, aiding Web3 in evolving towards a better direction.