Describe the bug
Metamask injects different APIs to window.ethereum object. On some sites ethereum provider has new API (i.e. https://uniswap.exchange/swap) https://docs.metamask.io/guide/ethereum-provider.html#methods-new-api and on others - the old API (i.e. app.compound.finance) https://docs.metamask.io/guide/ethereum-provider.html#methods-current-api
To Reproduce (REQUIRED)
ethereum.send("eth_requestAccounts"). You will get Promise pending. So there is Promise-based send method
ethereum.send("eth_requestAccounts"). You will get error inpage.js:1 MetaMask - RPC Error: The method undefined does not exist/is not available {code: -32601, message: "The method undefined does not exist/is not available"}. So I suppose that on this page was injected callback-based send API method.
Expected behavior
The window.ethereum object should have the same method signatures on both websites. In general, the new API or the old API should be injected into both websites.
I didn't clearly understand why metamask browser extension injects different API versions to different websites. What can cause side-effects on ethereum object so it becomes new-API or old-API provider?
Browser details (please complete the following information):
Hi @Kharabet, thanks for creating an issue.
We _do not_ inject different version of our Provider on different sites. I've managed to reproduce the behavior you're witnessing by executing the following line in the console of any dapp:
ethereum.send = ethereum.sendAsync
I believe that's what Compound is doing. We'll reach out to them and ask them to stop. Eventually, we'll probably Object.freeze the Provider object, but we have to take our time doing it, as we don't want to break dapps that are in production.
Since we can't fix this, I'm going to close this issue.
Before you go, I'd like to direct your attention to the following issue, which details some upcoming changes to our Provider, per EIP 1193: https://github.com/MetaMask/metamask-extension/issues/8077
You'll note that ethereum.send is being abandoned in favor of ethereum.request. The interface of send has been a bit of a mess historically, and the interface of request is designed to never break by taking a single, Object parameter, and returning Promises. See EIP 1193 for more details.
Can I ask why you needed to interact with different sites' providers, @Kharabet? Seems like a strange use case. Usually devs only care about their own site's provider.
@rekmarks , thank you for quick response!
I think that the overwrite of ethereum.send method is a side effect caused by web3-like libraries. Can you follow this issue https://github.com/NoahZinsmeister/web3-react/issues/79 and take a look at the sandbox https://codesandbox.io/s/web3-react-ethersjs-web3js-example-wgg13?file=/src/Web3jsComponent.tsx , please?
When I entered in console window.ethereum.send === window.ethereum.sendAsync, I got true

Then I commented some code that involves web3 library (here is my sandbox https://codesandbox.io/s/web3-react-ethersjs-web3js-example-lqm2l?file=/src/Web3jsComponent.tsx) and try it again. window.ethereum.send === window.ethereum.sendAsync return false and send method has correct signature.

So, I think there is some behavior inside Web3 constructor which overwrites window.ethereum`s methods.
Cool, so if we can correct this behavior in a shared library then the fix will propagate eventually to its consumers. Maybe we should just schedule the fix for after 1193 rolls out, so it can use the latest promise-based API.
Can I ask why you needed to interact with different sites' providers, @Kharabet? Seems like a strange use case. Usually devs only care about their own site's provider.
Actually, my aim was to use web3-react (https://github.com/NoahZinsmeister/web3-react) library for handling different user's wallet providers. But when I tried to setup the project with web3-react I faced with the metamask inpage provider erros. Then I found the same problem here https://github.com/NoahZinsmeister/web3-react/issues/79
I knew that this library (web3-react) is used by uniswap and I tried to figure out what can cause this error. For comparison, I tried to call window.ethereum.send("eth_requestAccounts) at other dapps (not only compound). Some of them failed as I described above (with MetaMask - RPC Error: The method undefined does not exist/is not available error).
Finally, I found that something affects/overwrites window.ethereum object so it can't provide new metamask API.
Great catch, @Kharabet. Thank you for investigating further! I should鈥檝e known it was [email protected].
The good news is that the request method won鈥檛 be overwritten when it鈥檚 launched in MetaMask v8 very soon. We expect most wallets to adopt that method and its signature over time.
Meanwhile, the payload/callback signature of sendAsync will continue to work. I advise against using send because of the multiple competing implementations of that method.
This seems to be finally resolved in https://github.com/ethereum/web3.js/pull/3378. Thanks!