Introducing a new pattern to discover multiple injected providers using window events to announce EIP-1193 providers in a two-communication standard between Ethereum libraries and Wallet peoviders.
NOTE: This EIP replaces the existing EIP5749
Introducing a new pattern to discover multiple injected providers using window events to announce EIP-1193 providers in a two-communication standard between Ethereum libraries and Wallet peoviders.
NOTE: This EIP replaces the existing EIP5749
What changes from EIP-5749?
Inspired by a discussion on the AllWalletDevs discord:
Is it possible for a dapp to access window.evmproviders
before all wallets have had a chance to modify the array? If so, should this proposal also specify an event dapps can subscribe to? Something like:
// In the dapp:
window.addEventListener("evmprovider", () => ...);
// In the wallet's content script:
modifyEvmProviders();
window.dispatchEvent(new Event("evmprovider", ...));
Reverted the āpostMessageā back to ādispatchEventā approach
Please read last comment on Github for context
Is name
in EIP6963ProviderInfo
ever translated into other languages, or is it always in the native language of the wallet?
So youāre using events because they can pass arbitrary JavaScript objects instead of postMessage
which can only pass transferable objects?
I feel pretty strongly that we should use postMessage
, perhaps transferring a MessagePort
to handle further communication.
I understand that this is a departure from how EIP-1193 works (which requires a request
method), but using postMessage
really does open up a lot of options for wallet design, some of which donāt even need special permissions to run.
You can implement an EIP-1193 compatible provider on top of a MessageChannel
like so:
class PortProvider implements ethers.Eip1193Provider {
private port: MessagePort;
constructor(port: MessagePort) {
this.port = port;
}
public request(request: Request): Promise<any> {
return new Promise((res, rej) => {
const channel = new MessageChannel();
channel.port1.onmessage = (evt) => res(evt.data);
channel.port1.onmessageerror = (evt) => rej(evt.data);
this.port.postMessage(request, "*", [channel.port2]);
});
}
}
For the rest of the example, you can take a look at Wallet-Test-Frameworkās dapp and fake chain halves.
Speaking for MetaMask, weāre more amenable to this proposal and are reviewing it internally. Thanks @pedrouid for driving, and to everyone who contributed!
On the postMessage
vs. dispatchEvent
discussion, we believe that dispatchEvent
is a good solution for the specific problem this EIP aims to solve, i.e. window.ethereum
clobbering. We also agree that thereās a need for a more generic messaging protocol, however:
externally_connectable
permission, which recently became possible after the Chrome team fixed this bug originally filed by @MicahZoltu.I agree with @rekmarks feedback that the need for a more generalized communication protocol is important but this EIP is not the place for this as it only focuses on EIP-1193 provider discovery which dispatchEvent
suffices
That being said a protocol with externally_connectable
is on my radar and that would be part of a bigger scope of work which would address both provider discovery and interface
Unfortunately externally_connectable
isnāt universally supported yet: 1319168 - Implement externally_connectable from a website
To the extent that we should concern ourselves with a browser that has less than 3% global market share, fair enough. Regardless, it shouldnāt be difficult to create a postMessage
-based version of a protocol written for externally_connectable
. Come to think of it, the standard should probably consist of a transport-agnostic message protocol with extensions for specific transports.
Yeah, extracting some bits of EIP-1193 into their own EIP might be worthwhile.
I know there are some significant drawbacks to this option, but I wanted to get a formal write-up of using scheme handlers for wallet discovery up just so we can discuss it more broadly.
Hereās the proposal pull request: Add EIP: Scheme-Handler Discovery Option for Wallets
And its discussion thread: SHADOW: A Scheme-Handler Discovery Option for Wallets
tl;dr use registerProtocolHandler
and <iframe src="web+evm://">
to connect to wallets over postMessage
.
I am curious, why are we not using window.evmproviders
, coupled with a great frontend library, EIP5749 can be a better solution
What are the possible drawbacks of EIP5749 over EIP6963?
EIP-6963 was created from a group that was pushing for adoption of EIP-5749
The main issue is that using a global window object can be manipulated and overwritten by different scripts
EIP-5749 also used a map instead of an array which caused issues with conflicting providers or even an attacker could replace another provider
EIP-6963 also introduces the concept of two identifiers (one local and one global) to ensure uniqueness of providers
EIP-6963 is the successor to EIP-5749 and shares the same authors
Understood, Its a great alternative way for EIP-5749
I have been implementing a wallet standard for EVM chains which is based on the Wallet standard
I myself was working on this problem, previously I was trying to solve this by assigning each wallet their own ānamespaceā in the browser, something like window.wallets.metamask
and window.wallets.backpack
, but then quickly realised it will not be adopted by wallets as it requires a lot of work and also that anybody can update the data from window
Will integrate this in ethereum wallet adapter, how is the adoption like, any wallets integrating currently?
The current proposal is also vulnerable to manipulation:
const foo = window.dispatchEvent;
window.dispatchEvent = function() {
console.log("here");
return foo.apply(this, arguments);
};
Trueā¦ an attacker can override or proxy the payloads for dispatchEvent
But itās better to take that risk than breaking compatibility with EIP-1193
My take is that we only get one take to break compatibility with EIP-1193 and if we are going to do it then the best candidate is CAIP-25
Itās a massive task to update all wallets and libraries to support an alternative provider interface (like EIP-1193) so this EIP-6963 is only tackling provider discovery
@pedrouid can you expand a bit further on why you think we only get one opportunity to break compatibility? Internet protocols have never followed that approach. Look at iterations on some of the following examples.
In every one of those cases thereās multiple iterations that occurred at various points of success with various degrees of adoption. Iām not following your line of reasoning that we only get one take to break compatibility. Similarly, isnāt the reason this is so contentious is because we are already breaking compatibility of the discovery mechanism portion of the protocol? Given the protocol encompasses more than just how messages are passed (window.ethereum
ā Event messaging) and what the interface looks like (EIP-1193 ā CAIP-25) such as what failure states occur, what RPC methods are supported, what happens if we need to support multiple interfaces, etc can you expand more on why you believe keeping EIP-1193 is necessary versus adding CAIP-25 interface now?
Trueā¦ an attacker can override or proxy the payloads for
dispatchEvent
Uh that seems like a showstopper to me. A malicious third party iframe such as an advertisement on a DApp being able to MITM the message in order to modify the to
address in a swap seems rather dangerous doesnāt it?
If an iframe is capable of modifying the window object in the way I described, weāre already screwed because the ethereum object lives on the window as well.
I canāt speak for @pedrouid, but breaking changes are painful, and we should make them judiciously.