metamask / detect-provider Goto Github PK
View Code? Open in Web Editor NEWA tiny utility for detecting the MetaMask Ethereum Provider, or any Provider compliant with EIP-1193.
License: ISC License
A tiny utility for detecting the MetaMask Ethereum Provider, or any Provider compliant with EIP-1193.
License: ISC License
In order to align with our other libraries, we should:
typedoc
as a dependency (use the same version as in the module template)build:docs
package script (refer to the module template)publish-docs
, publish-main-docs
, and publish-rc-docs
GitHub workflows (see module template)Dear team
I am using @metamask/provider to detect the provider in my webapp. Upon integration, I tested that it works fine on web (chrome extension) and iOS (metamask app). However, on android (metamask app), its not able to detect the provider. I've added alerts on the page as well to debug the same. On web, the alerts work fine. On android metamask app, it shows provider not found, please install metamask. I'm unable to understand why the same is not getting detected in android app. Please help here.
The url for my webapp - https://fervent-pike-7afa22.netlify.app
Found that when access https://portfolio.metamask.io in iOS Safari, and tap the "Connect MetaMask" button, it will redirect me to the MetaMask iOS app and open the in-app browser.
Can this be done by any API provided by MetaMask, or we need to handle it by ourselves with the MetaMask Deep Link (e.g. <a href="https://metamask.app.link/dapp/example.com" />)?
Module not found: Error: Can't resolve '@metamask/detect-provider' in '/Users/steve/sites/vue3-web3modal/src/Web3Modal/components/web3Modal'
Even After installation. Folder in node_modules is empty
The code:
useEffect(() => {
const loadProvider =async () => {
const provider = await detectEthereumProvider()
if (provider) {
const web3 = new Web3(provider);
setWeb3Api({
provider: provider,
web3: web3,
contract: null,
isLoading: false
});
} else {
setWeb3Api({
...web3Api,
isLoading: false
});
console.error('Please install MetaMask!')
}
}
loadProvider();
}, [])
I'm building a hybrid app using Ionic.
When I serve the app in the browser (Chrome), it works fine asking for the Metamask authentication (opens Metamask as expected).
However when I build that for native Android (I'm using Capacitor), even though the app opens on my Android phone normally after I launch it from Android Studio, it does not ask me to authenticate with Metamask.
After doing some troubleshoot I attached to the app (via Chrome Device Inspect) running on my real phone which is plugged via USB in my computer, and this is what I get on the native app:
common.js:166 @metamask/detect-provider: Unable to detect window.ethereum.
handleEthereum @ common.js:166
23:50:21.508 vendor.js:86490 ERROR Error: Uncaught (in promise): TypeError: Cannot read properties of null (reading 'request')
TypeError: Cannot read properties of null (reading 'request')
at src_app_home_home_module_ts.js:272:22
at ZoneDelegate.invoke (polyfills.js:413:30)
at Object.onInvoke (vendor.js:108502:25)
at ZoneDelegate.invoke (polyfills.js:412:56)
at Zone.run (polyfills.js:173:47)
at polyfills.js:1331:38
at ZoneDelegate.invokeTask (polyfills.js:447:35)
at Object.onInvokeTask (vendor.js:108490:25)
at ZoneDelegate.invokeTask (polyfills.js:446:64)
at Zone.runTask (polyfills.js:218:51)
at resolvePromise (polyfills.js:1268:35)
at polyfills.js:1338:21
at ZoneDelegate.invokeTask (polyfills.js:447:35)
at Object.onInvokeTask (vendor.js:108490:25)
at ZoneDelegate.invokeTask (polyfills.js:446:64)
at Zone.runTask (polyfills.js:218:51)
at drainMicroTaskQueue (polyfills.js:633:39)
at ZoneTask.invokeTask (polyfills.js:533:25)
at ZoneTask.invoke (polyfills.js:518:52)
at data.args.<computed> (polyfills.js:3076:36)
What should I do in order to have the native app being able to authenticate with the Metamask installed app?
Thanks!
To use this library with TypesScript, we must export the MetaMaskEthereumProvider interface.
It is not being exported; the code change should be as simple as adding an export keyword on line 1.
https://github.com/MetaMask/detect-provider/blob/main/src/index.ts
Hello, when I use the second account of my metamask wallet, this second account is not considered in execution. This is the first account that is always taken in the execution
In order to achieve standardization with other libraries, we should:
lint
and lint:fix
package scripts to reflect the module templatelint:changelog
, lint:dependencies
, lint:eslint
, lint:misc
(use the module template)eslint-config-prettier
, eslint-plugin-prettier
, prettier
, prettier-plugin-packagejson
provide a way to get typings for typescript projects.
Firstly, thanks for your work on this project! ๐
There are times when multiple wallet provider extensions are installed inside the users browser alongside MetaMask.
Some extensions play together nicely (for example Metamask & Coinbase) but some are simply overwriting the window.ethereum
property with their own injection (for example Metamask & Frame Companion).
In these cases, i would like to be able to call await detectEthereumProvider({mustBeMetamask: true})
and get a rejection if no MetaMask was found at window.ethereum
instead of a null resolution. This way we can handle this error in our dapps and provide some meaningful information to our users as to why they cannot connect.
Here is the diff that solved my problem:
diff --git a/src/index.ts b/src/index.ts
index 2141c3e..f3248ad 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -40,7 +40,7 @@ function detectEthereumProvider<T = MetaMaskEthereumProvider>({
let handled = false;
- return new Promise((resolve) => {
+ return new Promise((resolve, reject) => {
if ((window as Window).ethereum) {
handleEthereum();
@@ -72,13 +72,17 @@ function detectEthereumProvider<T = MetaMaskEthereumProvider>({
if (ethereum && (!mustBeMetaMask || ethereum.isMetaMask)) {
resolve(ethereum as unknown as T);
} else {
+ const expectedInjectionMissmatch = mustBeMetaMask && ethereum;
- const message = mustBeMetaMask && ethereum
+ const message = expectedInjectionMissmatch
? 'Non-MetaMask window.ethereum detected.'
: 'Unable to detect window.ethereum.';
!silent && console.error('@metamask/detect-provider:', message);
- resolve(null);
+
+ if(expectedInjectionMissmatch){
+ reject(new Error(message))
+ }
}
}
});
END
If a dApp redirects the user to the metamask mobile app using deep-link, then this library does not detect provider on page load,
const provider = await detectEthereumProvider();
if (provider) {
// Detected
} else {
// window.ethereum is undefined
}
When the dApp opens into the metamask mobile app browser, then always for the first time, it goes into the else condition and when page is reloaded, then it works fine.
Any suggestion is appreciated.
Thanks.
Hello, I can't solve this
Error: invalid BigNumber string (argument="value", value=" ", code=INVALID_ARGUMENT, version=bignumber/5.4.2)
My understanding is that this tool is a bit of hand-holding for new MetaMask developers. It solves common struggle of getting the provider in the context of browser/server-side environments.
However, the naming is confusing because it sounds like it will tell me which wallet is injected into the browser. To add insult to injury, you return whether the wallet is MM, but don't do this for other wallets.
I would suggest that the goal of the tool is clarified, and either 1) the tool should work for and report on all wallets, or 2) the name be changed to something like getProvider
so that option 1 can be developed elsewhere.
Could not find a declaration file for module '@metamask/detect-provider'. '/Users/xxxx/GitHub/yyyy/celo-web-signer/node_modules/@metamask/detect-provider/index.js' implicitly has an 'any' type. Try npm install @types/metamask__detect-provider
if it exists or add a new declaration (.d.ts) file containing declare module '@metamask/detect-provider';
ts(7016)
detectEthereumProvider get unknown return , it's error in the typescript
const detectProv = async () => {
const provider = await detectEthereumProvider()
let web3 = new Web3(provider)
let chainID = await web3.eth.getChainId()
window.alert(chainID)
if (window.ethereum) {
handleEthereum();
} else {
window.addEventListener('ethereum#initialized', handleEthereum, {
once: true,
});
// If the event is not dispatched by the end of the timeout,
// the user probably doesn't have MetaMask installed.
setTimeout(handleEthereum, 3000); // 3 seconds
}
function handleEthereum() {
const { ethereum } = window;
if (ethereum && ethereum.isMetaMask) {
console.log('Ethereum successfully detected!');
window.alert("detected")
// Access the decentralized web!
} else {
console.log('Please install MetaMask!');
}
}
}
I try to detect my MetaMask application as the provider via a web-site using detect-provider library. In the desktop, it works fine but when I try to detect the provider using the same website and connect it to via my phone, it does not detect any provider. Where am I wrong?
const provider = await detectEthereumProvider({ mustBeMetaMask: true })
await provider.request({ method: 'eth_requestAccounts' })
I am getting this using the request similar to the preview example:
import detectEthereumProvider from "@metamask/detect-provider";
const provider = await detectEthereumProvider({
mustBeMetaMask: true,
});
if (provider) {
const accounts = provider?.request?.({
method: "eth_requestAccounts",
});
return accounts?.[0];
};
TIL: Our current mobile script injection technique violates some CSPs!
I just got off a call with a team that currently can't use MetaMask because their page's CSP refuses to interact with an inline script.
It would help them if we also allowed connecting via a non-injected provider. Maybe we should set up detect-provider to bring its own inpage-provider, so it allows side-stepping this issue.
I'm reaching out to them to see what CSP this might be, I think a safely strict testing csp might be script-src: 'none'
.
Hi, I built a DAPP with React and React router but I got problem on Android Metamask browser only.
When the page is loaded directly from the URL https://example.com/mint
this library can't find any provider for my page.
However, this library will able to detect provider when I'm navigating from the main page https://example.com
to https://example.com/mint
I hope someone has resolved this issue and is able to help out. Thanks in advance.
I've added the dependency: npm i @metamask/detect-provider
But getting this error:
Failed to parse source map from '/home/pomatti/pjs/uniswap/uniswap-widget/node_modules/@metamask/detect-provider/src/index.ts' file: Error: ENOENT: no such file or directory, open '/home/pomatti/pjs/uniswap/uniswap-widget/node_modules/@metamask/detect-provider/src/index.ts'
Only thing I'm doing is importing it:
import detectEthereumProvider from '@metamask/detect-provider';
No idea why it is complaining:
The detect provider is unable to find the provider in Chrome, Android browser & Metamask App on version 10 of Android. Same web app works fine on desktop. Code is from the example given on the metamask docs. No CSP are set. Website was built using Webflow plus custom JS script for Web3. I'm at a complete lose as to what is happening, seems to be the same on dapps like pancakeswap except in Metamask App itself, when I choose Metamask it tells me: provider not found :/
npm package still dont have MetaMaskEthereumProvider interface from issue #41
Hello, I'm wondering - if I understand this correctly, if there is a window.ethereum
object on desktop, it's available synchronously on website load. But still, when you dont have metamask installed on the desktop, it still waits for the set timeout (3s by default). But this wait is not necessary in this situation on desktop, is it? Is it necessary on mobile, when the window.ethereum
is injected asynchronously and it can take some time, right?
Have you considered adding there another check after first check on window.ethereum
to check, if I am on desktop and if I was and initial window.ethereum
check would return false, the detectEthereumProvider
would resolve with null immediately? I can try submit a PR, if this makes sense and I understand this correctly. Thanks!:)
README say
The MetaMask extension provider is synchronously injected, while the MetaMask mobile provider is asynchronously injected.
But #38 (comment) gave different answer.
Mobile is different because we don't provide MetaMask through a browser extension, we offer a separate app. Apps can't talk directly to each other, so if you have a dapp open in iOS Chrome, iOS Safari, Android Chrome, Android Firefox, etc., the site can't know that you have MetaMask installed, because no such script is injected on the page like it is in the browser on desktop.
I thought that the latter was probably correct and that the README (and MetaMask Docs) should be amended.
Provider is not detected in Metamask browser.
My application is built with Nuxt, but the problem persists even when using the CDN version of detect-provider
, rather than the NPM package. I believe this approach should bypass any Nuxt-specific build issues.
I have tried increasing the timeout to 15 seconds.
Sometimes the provider is detected after refreshing the page, but this behavior is not consistent.
In order to align with our other libraries, we should:
16.x
from the CI matrixnode.engines
in package.json
to ^18.18 || >=20
To achieve consistency with our other libraries, we should
@types/jest
, jest
, jest-it-up
, and ts-jest
as dependencies (use same versions as in module template)test
package script to run jest && jest-it-up
instead of tape
(copy from the module template)test:watch
package script (copy from the module template)In order to align with our other libraries, we should ensure that the .github
directory reflects the module template.
Note that before this ticket is completed, we will need to:
NPM_TOKEN
, PUBLISH_DOCS_TOKEN
, and SLACK_WEBHOOK_URL
as secretsRepro:
Install Coinbase Wallet
const prov: any = await detectEthereumProvider({ mustBeMetaMask: true });
const chainId: string = await prov.request({ method: 'eth_chainId' });
Error: No provider selected for request eth_chainId
From the docs:
This may happen, for example, if the user has multiple wallets installed. After confirming that your code and dependencies are not modifying or overwriting window.ethereum, you should ask the user to ensure that they only have a single provider-injecting wallet enabled at any one time.
Any solutions other than messaging?
It appears that EIP-6963 is headed for finalization. Once this EIP has been implemented in all MetaMask clients, this package should be updated as well. In particular, we should define a new export requestProvider
(as implemented here), and deprecate (but not remove) the other exports / functionality of this package. Clients should continue to emit ethereum#initialized
for backwards compatibility.
Originally posted by @kingwill3 in #70
In order to achieve standardization with our other libraries, we should:
browserify
as a dependencytsup
as a dependency (copy version from module template)build.sh
build:types
package script (copy from module template)build
package script to use tsup
to compile the TypeScript code to JavaScript and tsc
to create TypeScript declaration files.typings
field in package.json
to types
exports
field to package.json
(copy from module template)module
field to package.json
(copy from module template)sideEffects
field to package.json
(copy from module template)dist/
in files
fieldA declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.