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

feat: Migrate eth_accounts and permittedChains to CAIP-25 endowment #27847

Open
wants to merge 289 commits into
base: main
Choose a base branch
from

Conversation

jiexi
Copy link
Contributor

@jiexi jiexi commented Oct 14, 2024

Description

This PR replaces the replaces the internal eth_accounts and endowment:permittedChains permission structure with a CAIP-25 endowment. It adds adapter logic to translate to and from the new internal CAIP-25 permissions. This change should be transparent to wallet users and to dapps except for one two cases, see below. This change is required in order to support CAIP-25 and CAIP-27 requests in a follow-up PR that enables the Multichain API.

Open in GitHub Codespaces

Related issues

Related: MetaMask/core#4784

Manual testing steps

There should be no user or dapp facing difference in behavior except:

  • When calling wallet_revokePermissions and specifying either eth_accounts or endowment:permitted-chains, the entire CAIP-25 permission will be revoked. It will appear to the dapp as if both eth_accounts and endowment:permitted-chains were revoked.
  • When calling wallet_getPermissions for a permitted dapp when the wallet is locked, eth_accounts should be returned in addition to endowment:permitted-chains. Currently there is a regression on main where only endowment:permitted-chains gets returned when the wallet is locked.
await window.ethereum.request({
 "method": "wallet_revokePermissions",
 "params": [
  {
    eth_accounts: {}
  }
],
});

await window.ethereum.request({
 "method": "wallet_revokePermissions",
 "params": [
  {
    'endowment:permitted-chains': {}
  }
],
});

await window.ethereum.request({
 "method": "wallet_getPermissions",
 "params": [],
});

Locked Wallet Behavior with dapp connected

Other than the one noted item below, this behavior matches that in main

  • eth_accounts returns []
  • wallet_getPermissions returns permissions incl eth_accounts
  • wallet_revokePermissions works as usual and revokes eth_accounts and revoke permitted-chains together
    • Note this fixes a regression in main where eth_accounts and permitted-chains aren't revoked as a pair if either is revoked
  • eth_requestAccounts prompts for unlock, after unlock returns accounts if any are permitted, otherwise shows connection prompt
  • wallet_requestPermissions prompts for unlock
  • signature methods fails with method or accounts not authorized
  • non-signature methods work as usual
  • accountsChanged empty array on lock. no event after revokePermissions which makes sense since the dapp was told empty array on lock and now it's actually empty array so no changes have occurred as far as the dapp should be concerned.

Screenshots/Recordings

Before

After

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Copy link
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

Copy link

socket-security bot commented Oct 14, 2024

Copy link

socket-security bot commented Oct 14, 2024

👍 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.

View full report↗︎

@jiexi
Copy link
Contributor Author

jiexi commented Oct 14, 2024

@metamask-bot update-policies

@jiexi
Copy link
Contributor Author

jiexi commented Oct 15, 2024

@metamaskbot update-policies

@metamaskbot
Copy link
Collaborator

Policies updated.
👀 Please review the diff for suspicious new powers.

🧠 Learn how: https://lavamoat.github.io/guides/policy-diff/#what-to-look-for-when-reviewing-a-policy-diff

@jiexi
Copy link
Contributor Author

jiexi commented Oct 15, 2024

@metamaskbot update-policies

@metamaskbot
Copy link
Collaborator

Policies updated.
👀 Please review the diff for suspicious new powers.

🧠 Learn how: https://lavamoat.github.io/guides/policy-diff/#what-to-look-for-when-reviewing-a-policy-diff

@jiexi
Copy link
Contributor Author

jiexi commented Oct 15, 2024

@SocketSecurity ignore npm/@metamask/[email protected]

i know that mcmire guy

@jiexi
Copy link
Contributor Author

jiexi commented Oct 15, 2024

@SocketSecurity ignore npm/@metamask/[email protected]

i still know that mcmire fellow

@jiexi
Copy link
Contributor Author

jiexi commented Oct 15, 2024

@SocketSecurity ignore npm/@metamask/[email protected]

the fetch isn't new, but even then it's fine because it fetches caller supplied url

@jiexi
Copy link
Contributor Author

jiexi commented Oct 15, 2024

@metamaskbot update-policies

@metamaskbot
Copy link
Collaborator

Policies updated.
👀 Please review the diff for suspicious new powers.

🧠 Learn how: https://lavamoat.github.io/guides/policy-diff/#what-to-look-for-when-reviewing-a-policy-diff

},
) {
let validParams;
try {
validParams = validateAddEthereumChainParams(req.params[0], end);
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Looks like we could remove the superfluous end parameter in a separate PR, it appears to be unused on main as well

Copy link
Contributor Author

Choose a reason for hiding this comment

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

PR against main here #29619

Copy link
Member

Choose a reason for hiding this comment

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

Great to see this converted to TypeScript, though perhaps we could do this in a separate PR as well, to reduce the impact of this one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure! 30b1773

*
* @param {string} origin - The origin whose exposed accounts to retrieve.
* @param {boolean} [suppressUnauthorizedError] - Suppresses the unauthorized error.
* @param {boolean} ignoreLock - If accounts should be returned even if the wallet is locked.
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps we can use an options object here instead, so that this is a named parameter. When reading the request-accounts method middleware, I was unsure what getAccounts(true) meant.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Comment on lines +177 to +179
res.result = Object.values(grantedPermissions).filter(
(value) => value !== undefined,
) as Json;
Copy link
Member

Choose a reason for hiding this comment

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

Nit: We can avoid type casting like this:

Suggested change
res.result = Object.values(grantedPermissions).filter(
(value) => value !== undefined,
) as Json;
res.result = Object.values(grantedPermissions).filter(
(
permission: ValidPermission<string, Caveat<string, Json>> | undefined,
): permission is ValidPermission<string, Caveat<string, Json>> =>
permission !== undefined,
);

A bit verbose, and still doesn't really validate that the return type matches the operation, but it does make a lot more clear what type transformation we're making here. And it preserves more type information.

Copy link
Member

Choose a reason for hiding this comment

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

Where do these undefined values come from anyway 🤔 I'm guessing it's because the controller considers it a valid possibility that the user would approve a set of zero permissions? But our UI doesn't allow that. Curious. Maybe we can find a way to update the type later to better reflect what it does.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've never actually seen undefined at runtime. Types seem to suggest this is possible though, but the types might just be incorrect.

I took this change from Elliot's suggestion

#27847 (comment)

({ type }) => type === Caip25CaveatType,
)?.value as Caip25CaveatValue | undefined;

if (caip25CaveatValue?.isMultichainOrigin) {
Copy link
Member

Choose a reason for hiding this comment

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

Do we still need this? I'm not sure why we'd want to throw an error in this case. This is what I thought we were trying to avoid - introducing obstacles to simultaneous use of both APIs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  • wallet_requestPermissions leave as is, that being the CAIP-25 permission is always replaced in it's entirety
  • wallet_add/switchEthereumChain switching, remove the isMultichainOrigin check
  • wallet_revokePermissions, remove the isMultichainOrigin check

Done here

8a3bc99

@desi desi assigned mikesposito and unassigned Gudahtt and mikesposito Jan 9, 2025
jiexi added 3 commits January 9, 2025 10:03
…rant (#29613)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Restores wallet_requestPermissions atomicity by delaying CAIP-25 grant
until after other grants if they are requested

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/29613?quickstart=1)

## **Related issues**

Fixes:

## **Manual testing steps**

1. Go to this page...
2.
3.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
@metamaskbot
Copy link
Collaborator

Builds ready [368fccb]
Page Load Metrics (1753 ± 69 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint30822051670348167
domContentLoaded14702086172414670
load14832092175314469
domInteractive26195514120
backgroundConnect1076352110
firstReactRender1678462512
getState56614147
initialActions01000
loadScripts10121573127712962
setupStore65711115
uiStartup16582356198217282

@metamaskbot
Copy link
Collaborator

Builds ready [30b1773]
Page Load Metrics (1694 ± 109 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint139722531702243117
domContentLoaded138821631671230110
load139721831694227109
domInteractive207440189
backgroundConnect96526157
firstReactRender15111352914
getState486202311
initialActions01000
loadScripts9951645126318187
setupStore670212211
uiStartup157129831975395190

github-merge-queue bot pushed a commit that referenced this pull request Jan 9, 2025
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Removes tests that are no longer applicable pertaining to permitted
chains.

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/29618?quickstart=1)

## **Related issues**

See:
#27847 (comment)

## **Manual testing steps**

1. Go to this page...
2.
3.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
`Migration ${version}: Invalid subject for origin "${origin}" of type ${typeof subject}`,
),
);
return state;
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps @Gudahtt can chime in here, but seems dangerous to bail out of the migration with a potentially partially modified state.

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah hmmm should these be continue instead?

Copy link
Contributor

Choose a reason for hiding this comment

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

pushing a PR with suggested change

Copy link
Contributor

Choose a reason for hiding this comment

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

github-merge-queue bot pushed a commit that referenced this pull request Jan 10, 2025
)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Removes unused `end` param in the ethereum-chain-util helpers
* validateChainId
* validateAddEthereumChainParams
* validateSwitchEthereumChainParams

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/29619?quickstart=1)

Extending E2E timeout to get past "no timings found" error:

```
flags = { "circleci": { "timeoutMinutes": 30 } }
```

## **Related issues**

See:
#27847 (comment)

## **Manual testing steps**

1. Go to this page...
2.
3.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
jiexi and others added 5 commits January 10, 2025 08:57
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/29634?quickstart=1)

## **Related issues**

Fixes:

## **Manual testing steps**

1. Go to this page...
2.
3.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
@jiexi jiexi requested a review from a team as a code owner January 10, 2025 18:16
@metamaskbot
Copy link
Collaborator

Builds ready [c1cbb26]
Page Load Metrics (1669 ± 56 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint43621171612293141
domContentLoaded15322090164211957
load15612106166911756
domInteractive258838199
backgroundConnect106430189
firstReactRender1675402411
getState5441184
initialActions01000
loadScripts11211602122310349
setupStore613821
uiStartup17602303187311254
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 15.31 KiB (0.27%)
  • ui: 691 Bytes (0.01%)
  • common: 132.64 KiB (1.58%)

@metamaskbot
Copy link
Collaborator

Builds ready [70b9f05]
Page Load Metrics (1567 ± 38 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint1480175115677938
domContentLoaded1471170415497234
load1480174415677938
domInteractive257336168
backgroundConnect75718147
firstReactRender15101523617
getState57114189
initialActions01000
loadScripts1033130411327235
setupStore672182110
uiStartup16822460191620699
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 15.31 KiB (0.27%)
  • ui: 691 Bytes (0.01%)
  • common: 132.64 KiB (1.58%)

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

Successfully merging this pull request may close these issues.

10 participants