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: Add Multichain API to Flask #27782

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

Conversation

jiexi
Copy link
Contributor

@jiexi jiexi commented Oct 10, 2024

Description

This branch adds support for the Multichain API to the Flask build of the Extension.

The existing API (via injected provider) should be completely unchanged.

(Very Briefly) What is the MetaMask Multichain API

  • Concurrent connection to any number of chains (no network switching)
  • Unified entry point for all chain ecosystems (EVM, BTC, Solana, Cosmos, Polkadot etc)
  • Accessible (on extension for chromium based browsers) via externally_connectable. Not accessible via an injected global like window.ethereum

Key Documents/Standards

mip = MetaMask Improvement Proposal

  • MIP-5 (Overview of the Multichain API)
    • CAIP-25 (new connection request API)
    • CAIP-27 (new request API, envelope with target scope/chainId included)
  • MIP-6 (Overview of how the Multichain API’s EVM support diverges from the 1193 injected provider)

Manual testing steps

yarn start:flask

Then

(RECOMMENDED) Use the Multichain Test Dapp

OR

Form requests manually

Open in GitHub Codespaces

Pre-merge author checklist

  • I’ve followed MetaMask Coding Standards.
  • 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 format if applicable
  • I’ve applied the right labels on the PR (see labeling guidelines). 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.

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.

@jiexi
Copy link
Contributor Author

jiexi commented Oct 14, 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

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↗︎

@shanejonas
Copy link
Contributor

this PR needs the patches from here: https://github.com/MetaMask/metamask-extension/pull/27847/files#r1801195961

@jiexi jiexi changed the base branch from caip-multichain to caip25-permission-migration October 15, 2024 16:18
@jiexi jiexi changed the title Multichain: migrate to core package feat: CAIP Multichain Oct 15, 2024
@jiexi
Copy link
Contributor Author

jiexi commented Oct 15, 2024

REMINDER: check the original feature branch PR for unresolved comments

@jiexi jiexi changed the title feat: CAIP Multichain feat: CAIP Multichain (New) Oct 15, 2024
@jiexi
Copy link
Contributor Author

jiexi commented Oct 15, 2024

TODO: Convert BARAD_DUR flag into flask feature flag

Done here #29003

@shanejonas shanejonas mentioned this pull request Oct 17, 2024
7 tasks
adonesky1 pushed a commit that referenced this pull request Oct 17, 2024
<!--
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/27940?quickstart=1)

## **Related issues**

Fixes:
#27782 (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/develop/.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/develop/.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
Copy link
Contributor Author

jiexi commented Oct 17, 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

@metamaskbot
Copy link
Collaborator

❌ Multichain API Spec Test Failed. View the report here.

Copy link

socket-security bot commented Oct 17, 2024

New, updated, and removed dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher
npm/@metamask/[email protected] None 0 1.69 MB metamaskbot
npm/@open-rpc/[email protected]2.2.4 Transitive: environment, eval +6 1.4 MB belfordz

🚮 Removed packages: npm/[email protected]

View full report↗︎

@metamaskbot
Copy link
Collaborator

❌ Multichain API Spec Test Failed. View the report here.

@mcmire
Copy link
Contributor

mcmire commented Mar 4, 2025

New problem: wallet_invokeMethod doesn't seem to be working correctly. It consistently times out. This is confirmable by running yarn build:flask and using the Multichain Test Dapp to call wallet_invokeMethod. Not sure what's going on here, but I will investigate that tomorrow.

@vandan
Copy link

vandan commented Mar 5, 2025

Yeah, I'm not sure what changed with wallet_invokeMethod. Only hint from my end is that this is a method that goes through some routing logic, which might also involve Snaps for non-EVM scopeStrings. Might be worth looking into any recent changes related to routing or related to SIP-26.

@vandan
Copy link

vandan commented Mar 5, 2025

Looks like it's currently working in the branch being used in the Frankenstein SIP-26 environment: https://github.com/MetaMask/MetaMask-planning/issues/3989

@mcmire
Copy link
Contributor

mcmire commented Mar 5, 2025

I think I got the wallet_invokeMethod tests working. I had deleted an end() while making an update to the middleware setup code in metamask-controller.js in a previous commit, so I added that back. Also, the setup for e2e tests changed since we added Anvil and that required some changes to the setup for the wallet_invokeMethod tests.

One thing I'm noticing, however, is that the tests for wallet_createSession sometimes time out. I'm not sure why, but that definitely seems to be intermittent, as I was able to get those tests passing after a couple of reruns. So we may have to watch out for that.

@metamaskbot
Copy link
Collaborator

Builds ready [0b26c90]
Page Load Metrics (1740 ± 103 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint34222981650349168
domContentLoaded14632237171420699
load150723061740214103
domInteractive24107402010
backgroundConnect1195332010
firstReactRender148125189
getState576232612
initialActions01000
loadScripts10641731128017383
setupStore76619199
uiStartup170527272000280135

}),
}),
);

Copy link
Member

@FrederikBolding FrederikBolding Mar 6, 2025

Choose a reason for hiding this comment

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

I just realized that a subset of the Snaps API is not made available over the multichain API. Not sure if that is intended, I was under the impression that we would still support wallet_* methods over the multichain API.

Probably not a blocker for merging though.

Copy link
Contributor

Choose a reason for hiding this comment

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

Which methods specifically?

Copy link
Member

Choose a reason for hiding this comment

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

wallet_getSnaps, wallet_invokeSnap, wallet_requestSnaps etc.

Copy link
Contributor

Choose a reason for hiding this comment

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

ah, yes that does seem like an oversight. Should be fairly easy to fix though. Agreed it shouldn't be a blocker for this PR

Copy link
Contributor

Choose a reason for hiding this comment

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

I will create a ticket for this

Copy link

Choose a reason for hiding this comment

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

That was actually intended. We expected to keep those in the "legacy API". But, we should discuss whether that is limiting is some way.

Copy link
Contributor

Choose a reason for hiding this comment

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

FrederikBolding
FrederikBolding previously approved these changes Mar 6, 2025
ffmcgee725
ffmcgee725 previously approved these changes Mar 6, 2025
Copy link
Contributor

@davidmurdoch davidmurdoch left a comment

Choose a reason for hiding this comment

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

just some comments/questions

@@ -30,6 +30,7 @@
"etherscan.io",
"execution.metamask.io",
"fonts.gstatic.com",
"foo.io",
Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, this endpoint should be mocked or the api-specs file updated. I have zero trust for the current owner of foo.io to not mess with our testing infrastructure.

There are TLDs that are specifically reserved for use in examples and tests, and have been guaranteed by IETF to never be registered as real TLDs:

  • .example
  • .invalid
  • .localhost
  • .test

Comment on lines 49 to 54
WATCH_ASSET: 'wallet_watchAsset',
WALLET_CREATE_SESSION: 'wallet_createSession',
WALLET_GET_SESSION: 'wallet_getSession',
WALLET_INVOKE_METHOD: 'wallet_invokeMethod',
WALLET_REVOKE_SESSION: 'wallet_revokeSession',
WALLET_SESSION_CHANGED: 'wallet_sessionChanged',
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: these new constants should be grouped with the other WALLET_ constant. Probably just a merge issue, but it'd be nice if they were together.

Copy link
Contributor

Choose a reason for hiding this comment

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

Makes sense! Updated in 6b690a1.

connectExternalCaip(...args);
} else {
const isDappConnecting = port.sender.tab?.id;
if (!process.env.MULTICHAIN_API || !isDappConnecting) {
Copy link
Contributor

@davidmurdoch davidmurdoch Mar 6, 2025

Choose a reason for hiding this comment

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

nit: using double negation with || here is every so slightly harder to read than a logical AND. Any reason for inverting the original condition (and if not, can you change it back pretty please :-D ).

@mcmire mcmire dismissed stale reviews from ffmcgee725 and FrederikBolding via 501c13d March 7, 2025 18:24
@metamaskbot
Copy link
Collaborator

Builds ready [63f0ba4]
Page Load Metrics (1797 ± 138 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint153527841787251121
domContentLoaded14912543173220699
load153629511797288138
domInteractive24542963
backgroundConnect11399668440
firstReactRender14108352512
getState5158333718
initialActions01000
loadScripts11201953131916378
setupStore76217157
uiStartup173344862144586281
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 6.39 KiB (0.10%)
  • ui: 0 Bytes (0.00%)
  • common: 1.98 KiB (0.02%)

@metamaskbot
Copy link
Collaborator

Builds ready [c700391]
Page Load Metrics (1978 ± 109 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint17322492196019393
domContentLoaded16962238187914067
load173526791978227109
domInteractive17102442110
backgroundConnect13422979947
firstReactRender15107412713
getState6344587636
initialActions01000
loadScripts12411694142610450
setupStore8116212613
uiStartup190242222410565271
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 6.39 KiB (0.10%)
  • ui: 0 Bytes (0.00%)
  • common: 1.98 KiB (0.02%)

Comment on lines +173 to +200
await hooks.requestPermissionApprovalForOrigin({
[Caip25EndowmentPermissionName]: {
caveats: [
{
type: Caip25CaveatType,
value: requestedCaip25CaveatValueWithSupportedEthAccounts,
},
],
},
});

const approvedCaip25Permission =
approvedPermissions[Caip25EndowmentPermissionName];
const approvedCaip25CaveatValue = approvedCaip25Permission?.caveats?.find(
(caveat) => caveat.type === Caip25CaveatType,
)?.value as Caip25CaveatValue;
if (!approvedCaip25CaveatValue) {
throw rpcErrors.internal();
}

const sessionScopes = getSessionScopes(approvedCaip25CaveatValue);

hooks.grantPermissions({
subject: {
origin,
},
approvedPermissions,
});
Copy link
Contributor

Choose a reason for hiding this comment

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

We should modify this to use the PermissionController.requestPermissions directly rather than ApprovalController -> PermissionController.grantPermissions

Same idea as the refactor we did here: https://github.com/MetaMask/metamask-extension/pull/30042/files#diff-6fbff2cfe97ac01b77296ef2122c7e0a5b3ff6a84b584b4d1a87482f35eea3d6

Copy link
Contributor

Choose a reason for hiding this comment

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

Its ok if we do this in a follow up PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Needs dev review
Development

Successfully merging this pull request may close these issues.