Skip to content
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

Initialize the MetaMask extension provider internally #834

Merged
merged 9 commits into from
Oct 10, 2023

Conversation

vsakos
Copy link
Contributor

@vsakos vsakos commented Oct 9, 2023

This PR uses an internal postMessage based inpage provider for communicating with the MetaMask extension instead of using the injected window.ethereum interface.

Copy link
Collaborator

@jordaaash jordaaash left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs some changes. I'm going to create a branch with a simplified approach.

if (
message?.target === 'metamask-inpage' &&
message.data?.name === 'metamask-provider' &&
message.data.data?.id === id
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're duck typing, so I don't think we care about the id here. I can't think of why we'd receive a message with a target of metamask-inpage, and a name of metamask-provider, and then the id would matter.

If we receive any message that quacks like Metamask, that means it's Metamask, and we can just proceed with checking for Snap support one time after that, and immediately stop trying if it fails.

if (!provider) return false;
async function metamaskRequest(request: Record<string, any>) {
return new Promise((resolve, reject) => {
const id = Math.floor(Math.random() * 1000000).toString();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure we need this, or need it to be anything other than a simple counter, see below.

return true;
const snaps = await Promise.race([
metamaskRequest({ method: 'wallet_getSnaps' }),
new Promise((resolve, reject) => setTimeout(() => reject('MetaMask provider not found'), 1000)),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
new Promise((resolve, reject) => setTimeout(() => reject('MetaMask provider not found'), 1000)),
new Promise((resolve, reject) => setTimeout(reject, 1000)),

We don't do anything with the rejection cause, so no reason to have it. However, I'm not sure why we need this race at all. We wait for a message that looks like Metamask, we should only call this one time.

import { registerWallet } from '@wallet-standard/wallet';
import { SolflareMetaMaskWallet } from './wallet.js';

let stopPolling = false;
let counter = 10;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we need polling, or any counter. That's If we add the message listener once on the window, then send a postMessage once, then we should be waiting for when Metamask is added. And if it's already been added, our message will reach it.

Comment on lines 42 to 52
window.removeEventListener('message', handleMessage);

if (message?.data.data.error) {
reject(message.data.data.error.message);
} else {
resolve(message.data.data.result);
}
}
}

return await isSnapSupported(provider);
} catch (error) {
return false;
}
window.addEventListener('message', handleMessage);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every time you call metamaskRequest you'd adding a new event listener. This shouldn't happen. And you're only removing the event listener the one time the message matches. This means you have up to 9 dangling event listeners creating memory leaks.

@jordaaash jordaaash merged commit 4341474 into anza-xyz:master Oct 10, 2023
1 check passed
@jordaaash jordaaash deleted the solflare-metamask-inpage-provider branch October 10, 2023 20:04
@ZhengYuTay
Copy link
Contributor

ZhengYuTay commented Oct 18, 2023

@jordansexton, this commit broke usage of Helium wallet if dApp have Solflare adapter and connecting through Helium

Suspect could be, helium is using postMessage as well but they never handled other cases of messages. Not sure if it affect any other as well

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants