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 CAIP-25 permission and adapters to @metamask/multichain #4784

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

Conversation

jiexi
Copy link
Contributor

@jiexi jiexi commented Oct 10, 2024

Explanation

This PR updates @metamask/multichain to provide types, CAIP-25 permission, and helpers/adapters for the new permission, which can be shared across the extension & mobile clients.

These tools and utilities will be used in both clients (mobile + extension)'s multichain API implementations.

File Overview

  • packages/multichain/src/adapters/: Helpers that get and set legacy permission values from and to the new CAIP-25 permission
  • packages/multichain/src/caip25Permission.ts: Constants, types, mutators, and a specification builder for a CAIP-25 permission
  • packages/multichain/src/index.ts: Barrel export
  • packages/multichain/src/scope/: Types for CAIP-217 and our internal normalized/flattened version of them. Additionally contains helpers for validating shape, normalizing/merging, and checking support (i.e. if the wallet is able to serve the chain with it's requested methods and notifications)

References

Upstream: #4812
Downstream: #4813

Key Multichain API Standards implemented here:

Open PR that uses this new package for migrating the legacy permissions to CAIP-25 permission in the extension: MetaMask/metamask-extension#27847

Changelog

@metamask/multichain

  • ADDED: TODO

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've highlighted breaking changes using the "BREAKING" category above as appropriate
  • I've prepared draft pull requests for clients and consumer packages to resolve any breaking changes

@jiexi jiexi requested a review from a team as a code owner October 10, 2024 22:49
@jiexi jiexi marked this pull request as draft October 10, 2024 22:49
jiexi and others added 3 commits October 10, 2024 15:54
## Explanation
This PR fixes a lot of the linting and typescript errors. still some
left but this covers a lot of it.


<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Changelog

<!--
If you're making any consumer-facing changes, list those changes here as
if you were updating a changelog, using the template below as a guide.

(CATEGORY is one of BREAKING, ADDED, CHANGED, DEPRECATED, REMOVED, or
FIXED. For security-related issues, follow the Security Advisory
process.)

Please take care to name the exact pieces of the API you've added or
changed (e.g. types, interfaces, functions, or methods).

If there are any breaking changes, make sure to offer a solution for
consumers to follow once they upgrade to the changes.

Finally, if you're only making changes to development scripts or tests,
you may replace the template below with "None".
-->

### `@metamask/package-a`

- **<CATEGORY>**: Your change here
- **<CATEGORY>**: Your change here

### `@metamask/package-b`

- **<CATEGORY>**: Your change here
- **<CATEGORY>**: Your change here

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've highlighted breaking changes using the "BREAKING" category
above as appropriate
- [ ] I've prepared draft pull requests for clients and consumer
packages to resolve any breaking changes

---------

Co-authored-by: Jiexi Luan <jiexiluan@gmail.com>
## Explanation

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->
Added ESM exports for multichain package

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Changelog

<!--
If you're making any consumer-facing changes, list those changes here as
if you were updating a changelog, using the template below as a guide.

(CATEGORY is one of BREAKING, ADDED, CHANGED, DEPRECATED, REMOVED, or
FIXED. For security-related issues, follow the Security Advisory
process.)

Please take care to name the exact pieces of the API you've added or
changed (e.g. types, interfaces, functions, or methods).

If there are any breaking changes, make sure to offer a solution for
consumers to follow once they upgrade to the changes.

Finally, if you're only making changes to development scripts or tests,
you may replace the template below with "None".
-->

### `@metamask/package-a`

- **<CATEGORY>**: Your change here
- **<CATEGORY>**: Your change here

### `@metamask/package-b`

- **<CATEGORY>**: Your change here
- **<CATEGORY>**: Your change here

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've highlighted breaking changes using the "BREAKING" category
above as appropriate
- [ ] I've prepared draft pull requests for clients and consumer
packages to resolve any breaking changes
@jiexi
Copy link
Contributor Author

jiexi commented Oct 11, 2024

@metamaskbot publish-preview

Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/accounts-controller": "18.2.2-preview-85a723e",
  "@metamask-previews/address-book-controller": "6.0.1-preview-85a723e",
  "@metamask-previews/announcement-controller": "7.0.1-preview-85a723e",
  "@metamask-previews/approval-controller": "7.1.0-preview-85a723e",
  "@metamask-previews/assets-controllers": "38.3.0-preview-85a723e",
  "@metamask-previews/base-controller": "7.0.1-preview-85a723e",
  "@metamask-previews/build-utils": "3.0.1-preview-85a723e",
  "@metamask-previews/chain-controller": "0.1.3-preview-85a723e",
  "@metamask-previews/composable-controller": "9.0.1-preview-85a723e",
  "@metamask-previews/controller-utils": "11.3.0-preview-85a723e",
  "@metamask-previews/ens-controller": "14.0.1-preview-85a723e",
  "@metamask-previews/eth-json-rpc-provider": "4.1.4-preview-85a723e",
  "@metamask-previews/gas-fee-controller": "20.0.1-preview-85a723e",
  "@metamask-previews/json-rpc-engine": "9.0.3-preview-85a723e",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.3-preview-85a723e",
  "@metamask-previews/keyring-controller": "17.2.2-preview-85a723e",
  "@metamask-previews/logging-controller": "6.0.1-preview-85a723e",
  "@metamask-previews/message-manager": "10.1.1-preview-85a723e",
  "@metamask-previews/multichain": "0.0.0-preview-85a723e",
  "@metamask-previews/name-controller": "8.0.1-preview-85a723e",
  "@metamask-previews/network-controller": "21.0.1-preview-85a723e",
  "@metamask-previews/notification-controller": "7.0.0-preview-85a723e",
  "@metamask-previews/notification-services-controller": "0.9.0-preview-85a723e",
  "@metamask-previews/permission-controller": "11.0.2-preview-85a723e",
  "@metamask-previews/permission-log-controller": "3.0.1-preview-85a723e",
  "@metamask-previews/phishing-controller": "12.0.3-preview-85a723e",
  "@metamask-previews/polling-controller": "10.0.1-preview-85a723e",
  "@metamask-previews/preferences-controller": "13.0.3-preview-85a723e",
  "@metamask-previews/profile-sync-controller": "0.9.7-preview-85a723e",
  "@metamask-previews/queued-request-controller": "5.1.0-preview-85a723e",
  "@metamask-previews/rate-limit-controller": "6.0.1-preview-85a723e",
  "@metamask-previews/selected-network-controller": "18.0.1-preview-85a723e",
  "@metamask-previews/signature-controller": "19.1.0-preview-85a723e",
  "@metamask-previews/transaction-controller": "37.2.0-preview-85a723e",
  "@metamask-previews/user-operation-controller": "15.0.1-preview-85a723e"
}

@jiexi
Copy link
Contributor Author

jiexi commented Oct 11, 2024

@metamaskbot publish-preview

Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/accounts-controller": "18.2.2-preview-a0bb278",
  "@metamask-previews/address-book-controller": "6.0.1-preview-a0bb278",
  "@metamask-previews/announcement-controller": "7.0.1-preview-a0bb278",
  "@metamask-previews/approval-controller": "7.1.0-preview-a0bb278",
  "@metamask-previews/assets-controllers": "38.3.0-preview-a0bb278",
  "@metamask-previews/base-controller": "7.0.1-preview-a0bb278",
  "@metamask-previews/build-utils": "3.0.1-preview-a0bb278",
  "@metamask-previews/chain-controller": "0.1.3-preview-a0bb278",
  "@metamask-previews/composable-controller": "9.0.1-preview-a0bb278",
  "@metamask-previews/controller-utils": "11.3.0-preview-a0bb278",
  "@metamask-previews/ens-controller": "14.0.1-preview-a0bb278",
  "@metamask-previews/eth-json-rpc-provider": "4.1.4-preview-a0bb278",
  "@metamask-previews/gas-fee-controller": "20.0.1-preview-a0bb278",
  "@metamask-previews/json-rpc-engine": "9.0.3-preview-a0bb278",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.3-preview-a0bb278",
  "@metamask-previews/keyring-controller": "17.2.2-preview-a0bb278",
  "@metamask-previews/logging-controller": "6.0.1-preview-a0bb278",
  "@metamask-previews/message-manager": "10.1.1-preview-a0bb278",
  "@metamask-previews/multichain": "0.0.0-preview-a0bb278",
  "@metamask-previews/name-controller": "8.0.1-preview-a0bb278",
  "@metamask-previews/network-controller": "21.0.1-preview-a0bb278",
  "@metamask-previews/notification-controller": "7.0.0-preview-a0bb278",
  "@metamask-previews/notification-services-controller": "0.9.0-preview-a0bb278",
  "@metamask-previews/permission-controller": "11.0.2-preview-a0bb278",
  "@metamask-previews/permission-log-controller": "3.0.1-preview-a0bb278",
  "@metamask-previews/phishing-controller": "12.0.3-preview-a0bb278",
  "@metamask-previews/polling-controller": "10.0.1-preview-a0bb278",
  "@metamask-previews/preferences-controller": "13.0.3-preview-a0bb278",
  "@metamask-previews/profile-sync-controller": "0.9.7-preview-a0bb278",
  "@metamask-previews/queued-request-controller": "5.1.0-preview-a0bb278",
  "@metamask-previews/rate-limit-controller": "6.0.1-preview-a0bb278",
  "@metamask-previews/selected-network-controller": "18.0.1-preview-a0bb278",
  "@metamask-previews/signature-controller": "19.1.0-preview-a0bb278",
  "@metamask-previews/transaction-controller": "37.2.0-preview-a0bb278",
  "@metamask-previews/user-operation-controller": "15.0.1-preview-a0bb278"
}

@jiexi
Copy link
Contributor Author

jiexi commented Oct 11, 2024

@metamaskbot publish-preview

Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/accounts-controller": "18.2.2-preview-1cd8ef2",
  "@metamask-previews/address-book-controller": "6.0.1-preview-1cd8ef2",
  "@metamask-previews/announcement-controller": "7.0.1-preview-1cd8ef2",
  "@metamask-previews/approval-controller": "7.1.0-preview-1cd8ef2",
  "@metamask-previews/assets-controllers": "38.3.0-preview-1cd8ef2",
  "@metamask-previews/base-controller": "7.0.1-preview-1cd8ef2",
  "@metamask-previews/build-utils": "3.0.1-preview-1cd8ef2",
  "@metamask-previews/chain-controller": "0.1.3-preview-1cd8ef2",
  "@metamask-previews/composable-controller": "9.0.1-preview-1cd8ef2",
  "@metamask-previews/controller-utils": "11.3.0-preview-1cd8ef2",
  "@metamask-previews/ens-controller": "14.0.1-preview-1cd8ef2",
  "@metamask-previews/eth-json-rpc-provider": "4.1.4-preview-1cd8ef2",
  "@metamask-previews/gas-fee-controller": "20.0.1-preview-1cd8ef2",
  "@metamask-previews/json-rpc-engine": "9.0.3-preview-1cd8ef2",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.3-preview-1cd8ef2",
  "@metamask-previews/keyring-controller": "17.2.2-preview-1cd8ef2",
  "@metamask-previews/logging-controller": "6.0.1-preview-1cd8ef2",
  "@metamask-previews/message-manager": "10.1.1-preview-1cd8ef2",
  "@metamask-previews/multichain": "0.0.0-preview-1cd8ef2",
  "@metamask-previews/name-controller": "8.0.1-preview-1cd8ef2",
  "@metamask-previews/network-controller": "21.0.1-preview-1cd8ef2",
  "@metamask-previews/notification-controller": "7.0.0-preview-1cd8ef2",
  "@metamask-previews/notification-services-controller": "0.9.0-preview-1cd8ef2",
  "@metamask-previews/permission-controller": "11.0.2-preview-1cd8ef2",
  "@metamask-previews/permission-log-controller": "3.0.1-preview-1cd8ef2",
  "@metamask-previews/phishing-controller": "12.0.3-preview-1cd8ef2",
  "@metamask-previews/polling-controller": "10.0.1-preview-1cd8ef2",
  "@metamask-previews/preferences-controller": "13.0.3-preview-1cd8ef2",
  "@metamask-previews/profile-sync-controller": "0.9.7-preview-1cd8ef2",
  "@metamask-previews/queued-request-controller": "5.1.0-preview-1cd8ef2",
  "@metamask-previews/rate-limit-controller": "6.0.1-preview-1cd8ef2",
  "@metamask-previews/selected-network-controller": "18.0.1-preview-1cd8ef2",
  "@metamask-previews/signature-controller": "19.1.0-preview-1cd8ef2",
  "@metamask-previews/transaction-controller": "37.2.0-preview-1cd8ef2",
  "@metamask-previews/user-operation-controller": "15.0.1-preview-1cd8ef2"
}

@jiexi
Copy link
Contributor Author

jiexi commented Oct 11, 2024

@metamaskbot publish-preview

Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/accounts-controller": "18.2.2-preview-c636def",
  "@metamask-previews/address-book-controller": "6.0.1-preview-c636def",
  "@metamask-previews/announcement-controller": "7.0.1-preview-c636def",
  "@metamask-previews/approval-controller": "7.1.0-preview-c636def",
  "@metamask-previews/assets-controllers": "38.3.0-preview-c636def",
  "@metamask-previews/base-controller": "7.0.1-preview-c636def",
  "@metamask-previews/build-utils": "3.0.1-preview-c636def",
  "@metamask-previews/chain-controller": "0.1.3-preview-c636def",
  "@metamask-previews/composable-controller": "9.0.1-preview-c636def",
  "@metamask-previews/controller-utils": "11.3.0-preview-c636def",
  "@metamask-previews/ens-controller": "14.0.1-preview-c636def",
  "@metamask-previews/eth-json-rpc-provider": "4.1.4-preview-c636def",
  "@metamask-previews/gas-fee-controller": "20.0.1-preview-c636def",
  "@metamask-previews/json-rpc-engine": "9.0.3-preview-c636def",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.3-preview-c636def",
  "@metamask-previews/keyring-controller": "17.2.2-preview-c636def",
  "@metamask-previews/logging-controller": "6.0.1-preview-c636def",
  "@metamask-previews/message-manager": "10.1.1-preview-c636def",
  "@metamask-previews/multichain": "0.0.0-preview-c636def",
  "@metamask-previews/name-controller": "8.0.1-preview-c636def",
  "@metamask-previews/network-controller": "21.0.1-preview-c636def",
  "@metamask-previews/notification-controller": "7.0.0-preview-c636def",
  "@metamask-previews/notification-services-controller": "0.9.0-preview-c636def",
  "@metamask-previews/permission-controller": "11.0.2-preview-c636def",
  "@metamask-previews/permission-log-controller": "3.0.1-preview-c636def",
  "@metamask-previews/phishing-controller": "12.0.3-preview-c636def",
  "@metamask-previews/polling-controller": "10.0.1-preview-c636def",
  "@metamask-previews/preferences-controller": "13.0.3-preview-c636def",
  "@metamask-previews/profile-sync-controller": "0.9.7-preview-c636def",
  "@metamask-previews/queued-request-controller": "5.1.0-preview-c636def",
  "@metamask-previews/rate-limit-controller": "6.0.1-preview-c636def",
  "@metamask-previews/selected-network-controller": "18.0.1-preview-c636def",
  "@metamask-previews/signature-controller": "19.1.0-preview-c636def",
  "@metamask-previews/transaction-controller": "37.2.0-preview-c636def",
  "@metamask-previews/user-operation-controller": "15.0.1-preview-c636def"
}

@jiexi
Copy link
Contributor Author

jiexi commented Oct 14, 2024

@metamaskbot publish-preview

Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/accounts-controller": "18.2.2-preview-42134f7e",
  "@metamask-previews/address-book-controller": "6.0.1-preview-42134f7e",
  "@metamask-previews/announcement-controller": "7.0.1-preview-42134f7e",
  "@metamask-previews/approval-controller": "7.1.0-preview-42134f7e",
  "@metamask-previews/assets-controllers": "38.3.0-preview-42134f7e",
  "@metamask-previews/base-controller": "7.0.1-preview-42134f7e",
  "@metamask-previews/build-utils": "3.0.1-preview-42134f7e",
  "@metamask-previews/chain-controller": "0.1.3-preview-42134f7e",
  "@metamask-previews/composable-controller": "9.0.1-preview-42134f7e",
  "@metamask-previews/controller-utils": "11.3.0-preview-42134f7e",
  "@metamask-previews/ens-controller": "14.0.1-preview-42134f7e",
  "@metamask-previews/eth-json-rpc-provider": "4.1.4-preview-42134f7e",
  "@metamask-previews/gas-fee-controller": "20.0.1-preview-42134f7e",
  "@metamask-previews/json-rpc-engine": "9.0.3-preview-42134f7e",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.3-preview-42134f7e",
  "@metamask-previews/keyring-controller": "17.2.2-preview-42134f7e",
  "@metamask-previews/logging-controller": "6.0.1-preview-42134f7e",
  "@metamask-previews/message-manager": "10.1.1-preview-42134f7e",
  "@metamask-previews/multichain": "0.0.0-preview-42134f7e",
  "@metamask-previews/name-controller": "8.0.1-preview-42134f7e",
  "@metamask-previews/network-controller": "21.0.1-preview-42134f7e",
  "@metamask-previews/notification-controller": "7.0.0-preview-42134f7e",
  "@metamask-previews/notification-services-controller": "0.9.0-preview-42134f7e",
  "@metamask-previews/permission-controller": "11.0.2-preview-42134f7e",
  "@metamask-previews/permission-log-controller": "3.0.1-preview-42134f7e",
  "@metamask-previews/phishing-controller": "12.0.3-preview-42134f7e",
  "@metamask-previews/polling-controller": "10.0.1-preview-42134f7e",
  "@metamask-previews/preferences-controller": "13.0.3-preview-42134f7e",
  "@metamask-previews/profile-sync-controller": "0.9.7-preview-42134f7e",
  "@metamask-previews/queued-request-controller": "5.1.0-preview-42134f7e",
  "@metamask-previews/rate-limit-controller": "6.0.1-preview-42134f7e",
  "@metamask-previews/selected-network-controller": "18.0.1-preview-42134f7e",
  "@metamask-previews/signature-controller": "19.1.0-preview-42134f7e",
  "@metamask-previews/transaction-controller": "37.2.0-preview-42134f7e",
  "@metamask-previews/user-operation-controller": "15.0.1-preview-42134f7e"
}

@jiexi
Copy link
Contributor Author

jiexi commented Oct 14, 2024

@metamaskbot publish-preview

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.

Okay, I've taken some time to look over the CAIPs and cross-check it with the code here this time. There is certainly a lot of validation code in this PR but that is all dictated in the spec, so it makes sense.

One thing I'm noticing is that we seem to just be checking the CAIP-25 request in this PR, and throwing if there are possible errors, but we're not creating a session, nor are we producing a response. Would that be up to the clients, or is that something that will automatically be handled somewhere else? Ah, I just noticed you have #4813 upcoming! I haven't reviewed this PR with that in mind. Feel free to reject a change if it doesn't fit into the bigger plan.

packages/multichain/src/caip25Permission.ts Outdated Show resolved Hide resolved
packages/multichain/src/caip25Permission.ts Outdated Show resolved Hide resolved
packages/multichain/src/caip25Permission.ts Outdated Show resolved Hide resolved
packages/multichain/src/caip25Permission.ts Show resolved Hide resolved
packages/multichain/src/caip25Permission.ts Outdated Show resolved Hide resolved
};

// Scope is already a CAIP-2 ID and has no references to flatten
if (!namespace || reference || !references) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This would only check if references is essentially absent, but if it's an empty array it would proceed — is that okay?

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 not understanding the case where !namespace happens. I will need to loop back on that but there shouldn't be a case where there is no extractable namespace from the scopeString that I can think of?

Copy link
Contributor

Choose a reason for hiding this comment

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

Also had some followup thoughts on your original question that I'm asking upstream in the validation flow that precedes this: https://github.com/MetaMask/core/pull/4784/files#r1833212893

Copy link
Member

Choose a reason for hiding this comment

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

This definitely looks broken in the case where references is empty. It would return an empty object then, essentially deleting the scope object.

Copy link
Contributor

Choose a reason for hiding this comment

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

added a check that the references array is not empty here: b04a941

And refactored slightly for clarity here: 41e0413

packages/multichain/src/scope/types.ts Outdated Show resolved Hide resolved
Comment on lines 27 to 44
// These non-prefixed types represent CAIP-217 Scope and
// ScopeObject as defined by the spec but without
// namespace-only Scopes (except for "wallet") and without
// the `references` array of CAIP References on the ScopeObject.
// These deviations from the spec are necessary as MetaMask
// does not support wildcarded Scopes, i.e. Scopes that only
// specify a namespace but no specific reference.
export type ScopeString = CaipChainId | KnownCaipNamespace.Wallet;
export type ScopeObject = {
methods: string[];
notifications: string[];
accounts: CaipAccountId[];
rpcDocuments?: string[];
rpcEndpoints?: string[];
};
export type ScopesObject = Record<CaipChainId, ScopeObject> & {
[KnownCaipNamespace.Wallet]?: ScopeObject;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar as above, would it be worth encapsulating these notes in JSDoc? Here is an attempt at expanding upon these slightly. If this is not a correct understanding then feel free to adjust.

Suggested change
// These non-prefixed types represent CAIP-217 Scope and
// ScopeObject as defined by the spec but without
// namespace-only Scopes (except for "wallet") and without
// the `references` array of CAIP References on the ScopeObject.
// These deviations from the spec are necessary as MetaMask
// does not support wildcarded Scopes, i.e. Scopes that only
// specify a namespace but no specific reference.
export type ScopeString = CaipChainId | KnownCaipNamespace.Wallet;
export type ScopeObject = {
methods: string[];
notifications: string[];
accounts: CaipAccountId[];
rpcDocuments?: string[];
rpcEndpoints?: string[];
};
export type ScopesObject = Record<CaipChainId, ScopeObject> & {
[KnownCaipNamespace.Wallet]?: ScopeObject;
};
/**
* Represents a `scopeString` as defined in
* [CAIP-217](https://chainagnostic.org/CAIPs/caip-217), with the exception that
* CAIP namespaces (aside from "wallet") are disallowed. This is necessary as
* MetaMask does not support "wildcarded" scopes in CAIP-25 requests, i.e.
* scopes that only specify a CAIP namespace but no specific reference (e.g.
* "eip155" vs. "eip155:1").
*/
export type ScopeString = CaipChainId | KnownCaipNamespace.Wallet;
/**
* Represents a `scopeObject` as defined in
* [CAIP-217](https://chainagnostic.org/CAIPs/caip-217), with the exception that
* the `references` property is disallowed. This is necessary as MetaMask does
* not support "wildcarded" scopes in CAIP-25 requests, i.e. scopes that only
* specify a CAIP namespace but no specific reference (e.g. "eip155" vs.
* "eip155:1").
*/
export type ScopeObject = {
methods: string[];
notifications: string[];
accounts: CaipAccountId[];
rpcDocuments?: string[];
rpcEndpoints?: string[];
};
/**
* Represents a keyed `scopeObject` as defined in
* [CAIP-217](https://chainagnostic.org/CAIPs/caip-217), with the exception that
* `scopeObject`s do not contain `references`. This is necessary as MetaMask
* does not support "wildcarded" scopes in CAIP-25 requests, i.e. scopes that
* only specify a CAIP namespace but no specific reference (e.g. "eip155" vs.
* "eip155:1").
*/
export type ScopesObject = Record<CaipChainId, ScopeObject> & {
[KnownCaipNamespace.Wallet]?: ScopeObject;
};

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually it seems like in addition to the deviations listed above, accounts is also a required property in our version whereas in the spec it is optional. Is there a reason for this?

Copy link
Contributor

Choose a reason for hiding this comment

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

// These non-prefixed types represent CAIP-217 Scope and
// ScopeObject as defined by the spec but without
// namespace-only Scopes (except for "wallet") and without
// the references array of CAIP References on the ScopeObject.
// These deviations from the spec are necessary as MetaMask
// does not support wildcarded Scopes, i.e. Scopes that only
// specify a namespace but no specific reference.

Ok so I think Jiexi's original comment is confusing since it suggests that we don't allow CAIP-25 requests that use the following format:

...
"method": "wallet_createSession",
  "params": {
    "requiredScopes": {
      "eip155": {
        "references": ["1", "137"],
        "methods": ["eth_sendTransaction", "eth_signTransaction", "eth_sign", "get_balance", "personal_sign"],
        "notifications": ["accountsChanged", "chainChanged"]
      },
...

Where the scopeString is only a namespace and then the references are specified in an array.

In fact we do allow this request format. What I have to assume Jiexi's original comment was meaning to indicate is that in our internal representations of this request/session we flatten out this format such that it becomes:

...
"method": "wallet_createSession",
  "params": {
    "requiredScopes": {
      "eip155:1": {
        "methods": ["eth_sendTransaction", "eth_signTransaction", "eth_sign", "get_balance", "personal_sign"],
        "notifications": ["accountsChanged", "chainChanged"]
      },
       "eip155:137": {
        "methods": ["eth_sendTransaction", "eth_signTransaction", "eth_sign", "get_balance", "personal_sign"],
        "notifications": ["accountsChanged", "chainChanged"]
      },
}
...

This is the reason for the two sets of types, those prefixed with "External" and those without:

  • ExternalScopeString & ScopeString
  • ExternalScopeObject & ScopeObject
  • ExternalScopesObject & ScopesObject

Given this I'm going to rephrase the JSDoc comments slightly and push them.

Copy link
Contributor

Choose a reason for hiding this comment

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

☝️ is also the explanation for this question👇

Actually it seems like in addition to the deviations listed above, accounts is also a required property in our version whereas in the spec it is optional. Is there a reason for this?

Notice that the ExternalScopeObject:

export type ExternalScopeObject = Omit<ScopeObject, 'accounts'> & {
  references?: CaipReference[];
  accounts?: CaipAccountId[];
};

resets the accounts property as optional. This is because the ExternalScopeObject is the type we expect in the CAIP-25 request itself for which, as you mentioned, the accounts property is optional.

in the internal ScopeObject however this property is not optional.

Perhaps using an internal prefix would be less confusing?

Copy link
Member

Choose a reason for hiding this comment

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

Perhaps using an internal prefix would be less confusing?

Yeah, I think so. Either that or something like Canonical or Normalized. Maybe Internal is best though.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I think using Internal/External (or Unofficial/Official, or MetaMask/Canonical, or something) would help. Otherwise it gives the impression that the spec is deviating from something we are setting, when it's the other way around.

And updating the JSDoc to represent what we are actually doing would be good too.

Copy link
Contributor

Choose a reason for hiding this comment

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

Added JSDocs here: 9c40d69

And added Internal prefix to these types here: 71f254a

packages/multichain/src/scope/constants.ts Outdated Show resolved Hide resolved
mcmire
mcmire previously approved these changes Oct 31, 2024
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.

On reviewing this again I don't think any of my comments are blocking, so I approve. Since we have another PR coming after this one we have another opportunity to tweak the names of ScopesObject if we can think of something better.

);
};

export const getEthAccounts = (
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Could you add TSDoc entries for each of these exported functions? Ideally we'd have them for all functions, but they're especially useful for the ones that get exported.

Copy link
Contributor

Choose a reason for hiding this comment

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

Added here: 8194afd

// namespace-only Scopes (except for "wallet") and without
// the `references` array of CAIP References on the ScopeObject.
// These deviations from the spec are necessary as MetaMask
// does not support wildcarded Scopes, i.e. Scopes that only
Copy link
Member

Choose a reason for hiding this comment

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

Off-topic question: What was the reason for not supporting wildcard scopes? Or was that just cut from the initial version for now to reduce scope?

Copy link
Contributor

Choose a reason for hiding this comment

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

I assume this question was addressed by #4784 (comment)

// Methods that do not belong to an ecosystem
export const KnownWalletRpcMethods: string[] = [
'wallet_registerOnboarding',
'wallet_scanQRCode',
Copy link
Member

Choose a reason for hiding this comment

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

Hmm. Technically it was introduced by an EIP, but it does seem useful outside of an Ethereum context. So maybe that's reason enough for it to belong here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah that was our thinking

return false;
}

// These assume that the namespace has a notion of chainIds
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 getting a little confused about where we landed on this question - whether we should be enforcing that scopes always contain a reference (either in the scopeString itself or in a references array)

CAIP-217 leaves the door open for scopes without references

Copy link
Contributor

Choose a reason for hiding this comment

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

If we are enforcing this, then there are a couple of validation cases I think we're missing:
ScopeString contains namespace only and references is either absent or an empty array.

Copy link

New dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher
npm/@metamask/api-specs@0.10.12 None 0 270 kB metamaskbot
npm/@metamask/eth-json-rpc-filters@7.0.1 None +1 214 kB lgbot

View full report↗︎

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