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

Implement EIP-6963 #263

Merged
merged 22 commits into from
Oct 11, 2023
Merged

Implement EIP-6963 #263

merged 22 commits into from
Oct 11, 2023

Conversation

rekmarks
Copy link
Member

@rekmarks rekmarks commented May 23, 2023

Implements EIP-6963 according to the current state of the specification. Adds two new top-level imports, eip6963AnnounceProvider and eip6963RequestProvider, used by us and the dapp, respectively.

For reference, here are some EIP6963ProviderInfo values that would work for us:

export const MetaMaskEIP6963ProviderInfo: EIP6963ProviderInfo = {
  uuid: uuid(),
  name: 'MetaMask', // Update depending on the build, probably
  icon: 'https://raw.githubusercontent.com/MetaMask/brand-resources/cb6fd847f3a9cc5e231c749383c3898935e62eab/SVG/metamask-fox.svg', // TODO: Find a shorter URL
};

The purpose of the uuid field is to help dapps notice if multiple wallets are claiming the same name. It needs to be a valid v4 UUID. IMO we should create a UUID at the point where we call announceProvider (i.e. the content script for the extension). We could also send it from the background.

@socket-security
Copy link

socket-security bot commented May 23, 2023

👍 Dependency issues cleared. Learn more about Socket for GitHub ↗︎

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

src/EIP6963.ts Outdated
Comment on lines 122 to 140
function isValidProviderDetail(
providerDetail: unknown,
): providerDetail is EIP6963ProviderDetail {
if (!isObject(providerDetail) || !isObject(providerDetail.info)) {
return false;
}
const { info } = providerDetail as EIP6963ProviderDetail;

return (
typeof info.icon === 'string' &&
isValidUrl(info.icon) &&
typeof info.name === 'string' &&
Boolean(info.name) &&
typeof info.uuid === 'string' &&
UUID_V4_REGEX.test(info.uuid) &&
typeof info.walletId === 'string' &&
Boolean(info.walletId)
);
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Normally I think we'd use superstruct or something for this, but it's important to keep the bundle size as small as possible.

Copy link
Member

Choose a reason for hiding this comment

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

superstruct is only 11.5 kB (or 3.4 kB gzipped), and @metmask/providers is 75.1 kB (or 21.1 kB gzipped). I don't think it makes a significant difference. 😅

Copy link
Contributor

Choose a reason for hiding this comment

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

Thoughts here? @rekmarks @Mrtenz

@socket-security
Copy link

socket-security bot commented Jun 8, 2023

No top level dependency changes detected. Learn more about Socket for GitHub ↗︎

src/EIP6963.ts Outdated Show resolved Hide resolved
src/EIP6963.ts Outdated Show resolved Hide resolved
jest.setup.browser.js Outdated Show resolved Hide resolved
src/EIP6963.test.ts Outdated Show resolved Hide resolved
src/EIP6963.test.ts Outdated Show resolved Hide resolved
@jiexi jiexi self-assigned this Jun 26, 2023
@jiexi jiexi marked this pull request as ready for review July 6, 2023 22:27
@jiexi jiexi requested a review from a team as a code owner July 6, 2023 22:27
});
});

// Reset JSDOM. This attempts to remove side effects from tests, however it does
Copy link
Member

Choose a reason for hiding this comment

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

I ran into JSDOM state issues when working on the phishing warning page too. In that case, I found it easiest to just use a real browser. See MetaMask/phishing-warning#62

Likewise for browser-passworder, that one is a plain library that we wanted to test in a real browser to ensure we were using browser APIs correctly. That uses playwright too: https://github.com/MetaMask/browser-passworder/blob/f870292ec5db729c8f69bbe4b2d3cff60053f333/test/index.spec.ts

Something to consider, if this needs further maintenance or continues to be a burden.

@jiexi
Copy link
Contributor

jiexi commented Sep 27, 2023

This should be caught up to spec now

src/EIP6963.ts Outdated Show resolved Hide resolved
@jiexi jiexi requested a review from Mrtenz October 3, 2023 23:23
@adonesky1 adonesky1 requested a review from mcmire October 5, 2023 17:38
Copy link
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

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

I read over EIP-6963, and the implementation makes sense. Just had minor questions about tests and type assertions.

{
files: ['jest.setup.browser.js'],
env: { browser: true },
// This file contains copypasta and we're not going to bother fixing these.
Copy link
Contributor

Choose a reason for hiding this comment

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

😅

Copy link
Contributor

Choose a reason for hiding this comment

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

/Users/jiexi/Projects/providers/jest.setup.browser.js
  25:1  error  All hooks must be wrapped in a describe block  jest/require-top-level-describe
  30:5  error  Missing JSDoc block description                jsdoc/require-description
  32:1  error  Missing JSDoc @param "type" description        jsdoc/require-param-description
  32:1  error  Missing JSDoc @param "type" type               jsdoc/require-param-type
  33:1  error  Missing JSDoc @param "listener" description    jsdoc/require-param-description
  33:1  error  Missing JSDoc @param "listener" type           jsdoc/require-param-type
  34:1  error  Missing JSDoc @param "options" description     jsdoc/require-param-description
  34:1  error  Missing JSDoc @param "options" type            jsdoc/require-param-type
  55:1  error  All hooks must be wrapped in a describe block  jest/require-top-level-describe

Copy link
Contributor

Choose a reason for hiding this comment

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

Definitely need to ignore jest/require-top-level-describe

Copy link
Contributor

Choose a reason for hiding this comment

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

do you feel it's worthwhile to add jsdoc to the rest? I can go either way

Copy link
Member Author

Choose a reason for hiding this comment

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

lol, this was me btw. It seems strictly not worth it, as I have a hard time imagining a lot of work being done in that file, but not my call of course!

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm good with this, just thought it was funny :)

src/EIP6963.ts Outdated Show resolved Hide resolved
src/EIP6963.ts Outdated Show resolved Hide resolved
src/EIP6963.ts Outdated Show resolved Hide resolved
src/EIP6963.ts Outdated Show resolved Hide resolved
src/EIP6963.test.ts Outdated Show resolved Hide resolved
src/EIP6963.ts Outdated Show resolved Hide resolved
@@ -20,4 +35,6 @@ export {
setGlobalProvider,
shimWeb3,
StreamProvider,
eip6963AnnounceProvider,
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, this name seems a bit mashed together. Too bad we can't put a type under a namespace of some kind.

Copy link
Contributor

Choose a reason for hiding this comment

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

hmm.. i'm not sure it would make sense to drop the EIP6963 prefixes either 😬

src/EIP6963.ts Outdated Show resolved Hide resolved
src/EIP6963.ts Outdated Show resolved Hide resolved
src/EIP6963.ts Show resolved Hide resolved
src/EIP6963.ts Outdated Show resolved Hide resolved
Copy link
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

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

Looks good to me!

@jiexi jiexi merged commit 215ae38 into main Oct 11, 2023
16 checks passed
@jiexi jiexi deleted the eip-6963 branch October 11, 2023 17:41
jiexi added a commit to MetaMask/metamask-extension that referenced this pull request Oct 11, 2023
## Explanation

Helps to alleviate `window.ethereum` conflicts by supporting an
alternative way for Dapps to discover and interact with providers. This
PR implements
[EIP-6963](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-6963.md)
which adds an async event based provider discovery standard.

~~NOTE: I'm not sure if we strictly need the changes I made that add
EIP-6963 support to the test dapp, but we probably want to add an e2e
test for EIP-6963 and I'm not sure if we want our tests to rely on an
external site like https://eip6963.org/ . Maybe we can test this by
running some js in page like we do for testing parts of the json rpc in
e2e environment.~~ I've added a spec for this that tests it directly in
the browser console instead

Ticket:
[mmp-869](MetaMask/MetaMask-planning#869)
Related: MetaMask/providers#263
~~Related: MetaMask/test-dapp#243

# Screenshot
<img width="470" alt="Screenshot 2023-09-27 at 4 41 13 PM"
src="https://github.com/MetaMask/metamask-extension/assets/918701/88a0e334-fed9-45e8-80a2-329cb4c94ded">

## Manual Testing Steps

* Install and enable a few other browser extension wallets
* Visit https://eip6963.org/
* MetaMask should show up in the list of providers and play nicely with
all of them

## Pre-merge author checklist

- [x] I've clearly explained:
  - [x] What problem this PR is solving
  - [x] How this problem was solved
  - [x] How reviewers can test my changes
- [x] Sufficient automated test coverage has been added

## Pre-merge reviewer checklist

- [ ] Manual testing (e.g. pull and build branch, run in browser, test
code being changed)
- [ ] PR is linked to the appropriate GitHub issue
- [ ] **IF** this PR fixes a bug in the release milestone, add this PR
to the release milestone

If further QA is required (e.g. new feature, complex testing steps,
large refactor), add the `Extension QA Board` label.

In this case, a QA Engineer approval will be be required.
k-g-j pushed a commit to MetaMask/metamask-extension that referenced this pull request Nov 1, 2023
## Explanation

Helps to alleviate `window.ethereum` conflicts by supporting an
alternative way for Dapps to discover and interact with providers. This
PR implements
[EIP-6963](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-6963.md)
which adds an async event based provider discovery standard.

~~NOTE: I'm not sure if we strictly need the changes I made that add
EIP-6963 support to the test dapp, but we probably want to add an e2e
test for EIP-6963 and I'm not sure if we want our tests to rely on an
external site like https://eip6963.org/ . Maybe we can test this by
running some js in page like we do for testing parts of the json rpc in
e2e environment.~~ I've added a spec for this that tests it directly in
the browser console instead

Ticket:
[mmp-869](https://github.com/MetaMask/MetaMask-planning/issues/869)
Related: MetaMask/providers#263
~~Related: MetaMask/test-dapp#243

# Screenshot
<img width="470" alt="Screenshot 2023-09-27 at 4 41 13 PM"
src="https://github.com/MetaMask/metamask-extension/assets/918701/88a0e334-fed9-45e8-80a2-329cb4c94ded">

## Manual Testing Steps

* Install and enable a few other browser extension wallets
* Visit https://eip6963.org/
* MetaMask should show up in the list of providers and play nicely with
all of them

## Pre-merge author checklist

- [x] I've clearly explained:
  - [x] What problem this PR is solving
  - [x] How this problem was solved
  - [x] How reviewers can test my changes
- [x] Sufficient automated test coverage has been added

## Pre-merge reviewer checklist

- [ ] Manual testing (e.g. pull and build branch, run in browser, test
code being changed)
- [ ] PR is linked to the appropriate GitHub issue
- [ ] **IF** this PR fixes a bug in the release milestone, add this PR
to the release milestone

If further QA is required (e.g. new feature, complex testing steps,
large refactor), add the `Extension QA Board` label.

In this case, a QA Engineer approval will be be required.
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.

5 participants