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 76 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

adonesky1 added a commit that referenced this pull request Oct 21, 2024
## Explanation

Creates the initial (empty) `@metamask/multichain` package to make
downstream additions to this package easier to review.

## References

Upstream: #4811
Downstream: #4784

## Changelog


### `@metamask/multichain`

- **ADDED**: Initial skeleton package for `@metamask/multichain`


## Checklist

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

---------

Co-authored-by: Mark Stacey <markjstacey@gmail.com>
Co-authored-by: Alex <adonesky@gmail.com>
Base automatically changed from initialize-caip-multichain to main October 21, 2024 18:57
adonesky1 and others added 9 commits October 21, 2024 14:21
## Explanation

Loosen `getEthAccounts` and `getPermittedEthChainIds` param type

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

Made a super shallow pass over this. I will give this a closer look tomorrow.

packages/multichain/jest.config.js Outdated Show resolved Hide resolved
packages/multichain/src/index.ts Outdated Show resolved Hide resolved
Comment on lines 36 to 50
export const KnownRpcMethods: Record<NonWalletKnownCaipNamespace, string[]> = {
eip155: Eip155Methods,
};

export const KnownWalletNamespaceRpcMethods: Record<
NonWalletKnownCaipNamespace,
string[]
> = {
eip155: WalletEip155Methods,
};

export const KnownNotifications: Record<NonWalletKnownCaipNamespace, string[]> =
{
eip155: ['accountsChanged', 'chainChanged', 'eth_subscription'],
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of forcing the types for these data structures, is it possible to use satisfies to enforce the shapes?

Suggested change
export const KnownRpcMethods: Record<NonWalletKnownCaipNamespace, string[]> = {
eip155: Eip155Methods,
};
export const KnownWalletNamespaceRpcMethods: Record<
NonWalletKnownCaipNamespace,
string[]
> = {
eip155: WalletEip155Methods,
};
export const KnownNotifications: Record<NonWalletKnownCaipNamespace, string[]> =
{
eip155: ['accountsChanged', 'chainChanged', 'eth_subscription'],
};
export const KnownRpcMethods = {
eip155: Eip155Methods,
} as const satisfies Record<NonWalletKnownCaipNamespace, string[]>;
export const KnownWalletNamespaceRpcMethods = {
eip155: WalletEip155Methods,
} as const satisfies Record<NonWalletKnownCaipNamespace, string[]>;
export const KnownNotifications = {
eip155: ['accountsChanged', 'chainChanged', 'eth_subscription'],
} as const satisfies Record<NonWalletKnownCaipNamespace, string[]>;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

doing this seems to break things where i use .include() or .filter() on these constants. An example error is Argument of type 'string' is not assignable to parameter of type '"wallet_addEthereumChain", which forces me to do change this:

  .filter(
    (method: string) => !KnownWalletNamespaceRpcMethods.eip155.includes(method),
  )

to

  .filter(
    (method: (typeof KnownWalletNamespaceRpcMethods.eip155)[number]) =>
      !KnownWalletNamespaceRpcMethods.eip155.includes(method),
  )

return parseCaipChainId(scopeString);
}

return {};
Copy link
Contributor

@mcmire mcmire Oct 22, 2024

Choose a reason for hiding this comment

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

Usually using an empty object to represent an unsuccessful result is a smell. Does it make sense to return something else such as null instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The idea was to be able to destructure without checking for null/undefined first.

Usage currently looks something like

const { namespace, reference } = parseScopeString(scopeString);
if (!namespace && !reference) {

}

vs

const parsedScopeString = parseScopeString(scopeString);
if (!parsedScopeString) {

}
const { namespace, reference } = parsedScopeString;

Comment on lines 25 to 29
export const KnownWalletRpcMethods: string[] = [
'wallet_registerOnboarding',
'wallet_scanQRCode',
];
const WalletEip155Methods = ['wallet_addEthereumChain'];
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems that by using string[] we are discarding type information that could be valuable later. For instance, if we wanted a type from this array we couldn't do that easily. Thoughts on removing and using as const?

Suggested change
export const KnownWalletRpcMethods: string[] = [
'wallet_registerOnboarding',
'wallet_scanQRCode',
];
const WalletEip155Methods = ['wallet_addEthereumChain'];
export const KnownWalletRpcMethods = [
'wallet_registerOnboarding',
'wallet_scanQRCode',
] as const;
const WalletEip155Methods = ['wallet_addEthereumChain'] as const;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

makes the types too narrow and difficult to consume downstream. Same problem as #4784 (comment)

];
const WalletEip155Methods = ['wallet_addEthereumChain'];

const Eip155Methods = MetaMaskOpenRPCDocument.methods
Copy link
Contributor

Choose a reason for hiding this comment

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

The type on this would be string[]. Similar comment as above, do we want to keep the type in case it's useful?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

makes the types too narrow and difficult to consume downstream. Same problem as #4784 (comment)

packages/multichain/src/scope/assert.test.ts Outdated Show resolved Hide resolved
packages/multichain/src/scope/authorization.test.ts Outdated Show resolved Hide resolved
packages/multichain/src/scope/validation.test.ts Outdated Show resolved Hide resolved
packages/multichain/src/caip25Permission.test.ts Outdated Show resolved Hide resolved
Copy link

socket-security bot commented Oct 23, 2024

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

@jiexi
Copy link
Contributor Author

jiexi commented Oct 23, 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-7d32a0b2",
  "@metamask-previews/address-book-controller": "6.0.1-preview-7d32a0b2",
  "@metamask-previews/announcement-controller": "7.0.1-preview-7d32a0b2",
  "@metamask-previews/approval-controller": "7.1.0-preview-7d32a0b2",
  "@metamask-previews/assets-controllers": "39.0.0-preview-7d32a0b2",
  "@metamask-previews/base-controller": "7.0.1-preview-7d32a0b2",
  "@metamask-previews/build-utils": "3.0.1-preview-7d32a0b2",
  "@metamask-previews/chain-controller": "0.1.3-preview-7d32a0b2",
  "@metamask-previews/composable-controller": "9.0.1-preview-7d32a0b2",
  "@metamask-previews/controller-utils": "11.4.0-preview-7d32a0b2",
  "@metamask-previews/ens-controller": "14.0.1-preview-7d32a0b2",
  "@metamask-previews/eth-json-rpc-provider": "4.1.5-preview-7d32a0b2",
  "@metamask-previews/gas-fee-controller": "21.0.0-preview-7d32a0b2",
  "@metamask-previews/json-rpc-engine": "10.0.0-preview-7d32a0b2",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.4-preview-7d32a0b2",
  "@metamask-previews/keyring-controller": "17.3.0-preview-7d32a0b2",
  "@metamask-previews/logging-controller": "6.0.1-preview-7d32a0b2",
  "@metamask-previews/message-manager": "11.0.0-preview-7d32a0b2",
  "@metamask-previews/multichain": "0.0.0-preview-7d32a0b2",
  "@metamask-previews/name-controller": "8.0.1-preview-7d32a0b2",
  "@metamask-previews/network-controller": "21.1.0-preview-7d32a0b2",
  "@metamask-previews/notification-controller": "7.0.0-preview-7d32a0b2",
  "@metamask-previews/notification-services-controller": "0.12.0-preview-7d32a0b2",
  "@metamask-previews/permission-controller": "11.0.2-preview-7d32a0b2",
  "@metamask-previews/permission-log-controller": "3.0.1-preview-7d32a0b2",
  "@metamask-previews/phishing-controller": "12.0.3-preview-7d32a0b2",
  "@metamask-previews/polling-controller": "11.0.0-preview-7d32a0b2",
  "@metamask-previews/preferences-controller": "13.1.0-preview-7d32a0b2",
  "@metamask-previews/profile-sync-controller": "0.9.7-preview-7d32a0b2",
  "@metamask-previews/queued-request-controller": "5.1.0-preview-7d32a0b2",
  "@metamask-previews/rate-limit-controller": "6.0.1-preview-7d32a0b2",
  "@metamask-previews/selected-network-controller": "18.0.2-preview-7d32a0b2",
  "@metamask-previews/signature-controller": "20.1.0-preview-7d32a0b2",
  "@metamask-previews/transaction-controller": "37.3.0-preview-7d32a0b2",
  "@metamask-previews/user-operation-controller": "16.0.0-preview-7d32a0b2"
}

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.

Did another pass. Wasn't able to get to the meat of the code today, so a lot of comments are relatively surface-level still. I still need to read through the CAIPs to understand more context, so I will try doing that tomorrow.


export const Caip25CaveatType = 'authorizedScopes';

export const Caip25CaveatFactoryFn = (value: Caip25CaveatValue) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the Fn at the end of the name here necessary, since Factory is already in the name?

Alternatively, is there anything really special about this function as opposed to other functions? What about calling this createCaip25Caveat?

Suggested change
export const Caip25CaveatFactoryFn = (value: Caip25CaveatValue) => {
export const createCaip25Caveat = (value: Caip25CaveatValue) => {

* @param caip25CaveatValue - The CAIP-25 permission caveat value to remove the scope from.
* @returns The updated CAIP-25 permission caveat value.
*/
export function removeScope(
Copy link
Contributor

Choose a reason for hiding this comment

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

If this function is intended to operate on a caveat, what are your thoughts on putting the caveat as the first argument? I feel like this would be a more intuitive interface than putting it second. It would also allow for adding more arguments in the future without needing to rearrange the order of the arguments.

});
});

it('builds the expected permission specification', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

What is "it" here? Is it the endowment, or the thing that builds the endowment?

expect(specification.endowmentGetter()).toBeNull();
});

it('builds the caveat', () => {
Copy link
Contributor

@mcmire mcmire Oct 23, 2024

Choose a reason for hiding this comment

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

The "it" here seems to be different from the previous test.

It seems that in this test file, we are testing different parts of this module. If that is true, what are your thoughts on using describes to represent those parts so we know what exactly is being tested? For instance:

describe('caip25EndowmentBuilder', () => {
  describe('specificationBuilder', () => {
    it('builds the expected permission specification', () => {
      // ...
    });
  });
});

describe('Caip25CaveatFactoryFn', () => {
  it('builds the caveat', () => {
    // ...
  });
});

describe('Caip25CaveatMutatorFactories', () => {
  describe('.authorizedScopes', () => {
    describe('removeScope', () => {
      // ...
    });

    describe('removeAccount', () => {
      // ...
    });
  });
});

}));
const MockScopeAssert = jest.mocked(ScopeAssert);

const { removeAccount } = Caip25CaveatMutatorFactories[Caip25CaveatType];
Copy link
Contributor

Choose a reason for hiding this comment

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

We seem to test removeAccount as it comes from this Caip25CaveatMutatorFactories object, but we are testing removeScope as it is exported from the whole module, even though this object also has a removeScope method. Is that intentional?

return mergedScopeObject;
};

export const mergeScopes = (
Copy link
Contributor

@mcmire mcmire Oct 23, 2024

Choose a reason for hiding this comment

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

Hmm, it looks like we have two similarly sounding functions. I can see why: one operates on a pair of ScopeObjects, whereas this one operates on a pair of ScopesObjects. That seems somewhat confusing.

I know naming is hard, but since ScopesObject organizes ScopeObjects by scopeString, maybe it's worth encoding that into the name somehow? Perhaps literally scopeObjectsByScopeString. Then this function would become mergeScopeObjectsByScopeString (which is an accidental play on words, I know, but I think still makes sense?).


describe('Scope Validation', () => {
describe('isValidScope', () => {
it.each([
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar comment as elsewhere. I am finding this a bit difficult to read in its current form. I end up having to go back and forth between the data that's used to construct the test and the actual body of the test to understand what each of these values means and how they're used. What are your thoughts on writing these tests out?

it('does not throw an error if required scopes are defined but none are valid', () => {
expect(
validateScopes(
{ 'eip155:1': {} as unknown as ExternalScopeObject },
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 know that this is not an ExternalScopeObject and so we expect this to fail type checking, should we indicate that instead?

Suggested change
{ 'eip155:1': {} as unknown as ExternalScopeObject },
// @ts-expect-error Intentionally invalid input
{ 'eip155:1': {} },

(similar for below cases)

@@ -3,8 +3,16 @@
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist",
"rootDir": "./src"
"rootDir": "./src",
"resolveJsonModule": true
Copy link
Contributor

Choose a reason for hiding this comment

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

What are we using this for? I didn't see a JSON file being imported, but I might have missed it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

type Hex,
type NonEmptyArray,
} from '@metamask/utils';
import { strict as assert } from 'assert';
Copy link
Contributor

Choose a reason for hiding this comment

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

Note that this makes this module dependent on Node (or at least, it means that whatever bundler the consumer is using needs to fill in this module). Is that intentional? Is there a way to use plain JavaScript instead?

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.

4 participants