* Migrate to new controller packages
`@metamask/controllers` is deprecated, and most of the controllers that
lived here are now located in their own package ([1]). This commit
replaces `@metamask/controllers` in `package.json` with references to
these packages and updates `import` lines to match.
[1]: https://github.com/MetaMask/controllers/pull/831
* Support GitHub registry for draft PRs (#16549)
* Add additional allowed host to lockfile linter
* Update LavaMoat policies
* Add policy exception for nanoid
* Add additional nanoid overrides
* Update LavaMoat policies again
* Bump controller packages
* Update lavamoat
* Bump controller packages
* Update packages to v1.0.0
* Expand gitignore comment
* Unpin controller dependencies, using ^ range instead
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
* Remove 3box feature and delete ThreeBoxController
Lint locale messages
lavamoat policy updates
* Restore 3Box user trait with value `false`
The 3Box user trait has been restored and hard-coded as `false`. This
ensures that users don't get stuck in our metrics as having this trait.
A deprecation comment has been left in various places for this trait.
* Remove unused state
* Remove additional 3box-related things
* Run `yarn-deduplicate`
* Restore migration that was lost while rebasing
* Remove obsolete override
* Remove additional unused resolutions/dependencies
* Update LavaMoat policies
* Remove obsolete security advisory ignore entries
* Remove 3Box fixture builder method
* Update unit tests
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
This update includes fixes for our `block-ref` and `retry-on-empty`
middleware.
The `block-ref` middleware resolves the block reference `latest` to a
specific block number, the latest one we are aware of. This is meant to
protect against situations where the network gives inconsistent answers
for what the latest block number is due to some nodes being out-of-sync
with each other (this was a frequent problem years ago with Infura).
It was broken in that the `latest` resolution was failing, and we were
submitting an additional redundant request to Infura for each request.
The `retry-on-empty` middleware is meant to retry certain methods
when they return an empty response. This was also meant to deal with
network synchronization issues that were more common years ago. This
middleware works by making a "child" request over and over until either
a retry limit is reached, or a non-empty response is received.
It was broken in that the final response recieved was thrown away, so
it's as though the middleware was not used. Except that it did result
in additional redundant network requests.
As a result of this update we should see that the extension is more
resilient to certain network synchronization issues. But this is
difficult to test, and these issues may not happen in production
anymore today.
We should see a reduction in requests to Infura as well. This should
be easier to test.
Add tests for the `block-tracker-inspector` middleware — which makes
sure that the block tracker never has a reference to the latest block
which is less than a block number that shows up in an RPC method's
response — and the Infura middleware — which takes care of sending the
request to Infura, and will retry the request up to 5 times if Infura
sends back a certain type of error.
Note that the `retry-on-empty` middleware is not tested because it
currently has a [bug][1] which is making it ineffective.
[1]: https://github.com/MetaMask/eth-json-rpc-middleware/issues/139
* Update `eth-json-rpc-infura`
The package `eth-json-rpc-infura@5` has been updated to
`@metamask/eth-json-rpc-infura@7`. This update includes TypeScript
support, and it drops support for older node.js versions. The exports
have also been changed from default to named exports.
See here for a full list of changes: https://github.com/MetaMask/eth-json-rpc-infura/blob/main/CHANGELOG.md#700
* Fix LavaMoat policy issue
The `web3` package used by `@metamask/controllers` unintentionally
overwrites the `XMLHttpRequest` global, which breaks things. This was
fixed by revoking `web3`'s write access to that global using a policy
override.
Previously this policy override was applied to `web3`, but for some
unknown reason, this update caused that override to no longer apply.
The Sentry `Dedupe` integration has been filtering out our events, even
when they were never sent due to our `beforeSend` handler. It was
wrongly identifying them as duplicates because it has no knowledge of
`beforeSend` or whether they were actually sent or not.
To resolve this, the filtering we were doing in `beforeSend` has been
moved to a Sentry integration. This integration is installed ahead of
the `Dedupe` integration, so `Dedupe` should never find out about any
events that we filter out, and thus will never consider them as sent
when they were not.
Recently in #15468 the name of the scripts task used by the LavaMoat
policy generation script was renamed from `scripts:prod` to
`scripts:dist`, but we neglected to change this name in the LavaMoat
policy generation script itself.
The script task has now been updated so that the script works again,
and the LavaMoat policy generation script has been re-run.
As we convert parts of the codebase to TypeScript, we will want a way to
track progress. This commit adds a dashboard which displays all of the
files that we wish to convert to TypeScript and which files we've
already converted.
The list of all possible files to convert is predetermined by walking
the dependency graph of each entrypoint the build system uses to compile
the extension (the files that the entrypoint imports, the files that the
imports import, etc). The list should not need to be regenerated, but
you can do it by running:
yarn ts-migration:enumerate
The dashboard is implemented as a separate React app. The CircleCI
configuration has been updated so that when a new commit is pushed, the
React app is built and stored in the CircleCI artifacts. When a PR is
merged, the built files will be pushed to a separate repo whose sole
purpose is to serve the dashboard via GitHub Pages (this is the same
way that the Storybook works). All of the app code and script to build
the app are self-contained under
`development/ts-migration-dashboard`. To build this app yourself, you
can run:
yarn ts-migration:dashboard:build
or if you want to build automatically as you change files, run:
yarn ts-migration:dashboard:watch
Then open the following file in your browser (there is no server
component):
development/ts-migration-dashboard/build/index.html
Finally, although you shouldn't have to do this, to manually deploy the
dashboard once built, you can run:
git remote add ts-migration-dashboard git@github.com:MetaMask/metamask-extension-ts-migration-dashboard.git
yarn ts-migration:dashboard:deploy
We use the `rc` package to read the `.metamaskrc` configuration file,
which is in "ini" format. This package has been replaced by the `ini`
package.
The `rc` package was not actively maintained, and it has had recent
security vulnerabilities. But most importantly, the config object
returned by `rc` includes a bunch of extra information that made build
script validation [1] difficult to implement. Specifically, it made it
challenging to ensure no extra environment variables were present.
The `ini` package on the other hand is simple, well maintained, and
is simpler to use. This package doesn't add any extra properties to the
object it returns, making validation easy.
[1]: https://github.com/MetaMask/metamask-extension/issues/15003
The build script now uses `yargs` rather than `minimist`. The CLI is
now better documented, and we have additional validation for each
option.
A patch for `yargs` was required because it would blow up on the line
`Error.captureStackTrace`. For some reason when running under LavaMoat,
that property did not exist.
Closes#12766
* origin/develop: (131 commits)
Update `protobufjs` and remove obsolete advisory exclusion (#14841)
Include snap version in pill (#14803)
Update PULL_REQUEST_TEMPLATE.md (#14790)
fix: keystone transaction qrcode has no white spacing (#14798)
Snap notifications integration (#14605)
Upgrade @metamask/eth-ledger-bridge-keyring (#14799)
snaps-skunkworks@0.15.0 (#14772)
Fix proptype errors in network dropdown, tx list item details, and account details modal tests (#14747)
Ensure transaction type is correctly updated on edit (#14721)
Add fiat onboarding for AVAX and MATIC through Wyre (#14683)
Bump @metamask/contract-metadata from 1.33.0 to 1.35.0 (#14791)
Slight cleanup of constants/transactions, useTransactionDisplayData, and TransactionIcon (#14784)
Migrate the "estimateGas" API call to "getFees" for STX (#14767)
Ignore advisory GHSA-wm7h-9275-46v2 (#14789)
Adding flag for MV3 (#14762)
Add types to send state (#14740)
Remove site origin on snap install (#14752)
Update design tokens library from 1.5 to 1.6 WIP (#14732)
Enables the "Safe Transaction From" copy for safeTransferFrom transactions (#14769)
remove draft transaction (#14701)
...
* Create `.zip` files deterministically
Our build system now creates `.zip` archives deterministically.
Previously the `.zip` file would differ between builds even when the
files being archived were identical. This was because the order the
files were passed in was non-deterministic, and the `mtime` for each
file was different between builds.
The files are now sorted before being zipped, and the `mtime` for each
file has been set to the unix epoch.
* Update lavamoat build policy
* Create `.zip` files deterministically
Our build system now creates `.zip` archives deterministically.
Previously the `.zip` file would differ between builds even when the
files being archived were identical. This was because the order the
files were passed in was non-deterministic, and the `mtime` for each
file was different between builds.
The files are now sorted before being zipped, and the `mtime` for each
file has been set to the unix epoch.
* Update lavamoat build policy
This commit modifies the build system so that TypeScript files can be
transpiled into ES5 just like JavaScript files.
Note that this commit does NOT change the build system to run TypeScript
files through the TypeScript compiler. In other words, no files will be
type-checked at the build stage, as we expect type-checking to be
handled elsewhere (live, via your editor integration with `tsserver`,
and before a PR is merged, via `yarn lint`). Rather, we merely instruct
Babel to strip TypeScript-specific syntax from any files that have it,
as if those files had been written using JavaScript syntax alone.
Why take this approach? Because it prevents the build process from being
negatively impacted with respect to performance (as TypeScript takes a
significant amount of time to run).
It's worth noting the downside of this approach: because we aren't
running files through TypeScript, but relying on Babel's [TypeScript
transform][1] to identify TypeScript syntax, this transform has to keep
up with any syntax changes that TypeScript adds in the future. In fact
there are a few syntactical forms that Babel already does not recognize.
These forms are rare or are deprecated by TypeScript, so I don't
consider them to be a blocker, but it's worth noting just in case it
comes up later. Also, any settings we place in `tsconfig.json` will be
completely ignored by Babel. Again, this isn't a blocker because there
are some analogs for the most important settings reflected in the
options we can pass to the transform. These and other caveats are
detailed in the [documentation for the transform][2].
[1]: https://babeljs.io/docs/en/babel-plugin-transform-typescript
[2]: https://babeljs.io/docs/en/babel-plugin-transform-typescript#caveats
This commit allows developers to write TypeScript files and lint them
(either via a language server in their editor of choice or through the
`yarn lint` command).
The new TypeScript configuration as well as the updated ESLint
configuration not only includes support for parsing TypeScript files,
but also provides some compatibility between JavaScript and TypeScript.
That is, it makes it possible for a TypeScript file that imports a
JavaScript file or a JavaScript file that imports a TypeScript file to
be linted.
Note that this commit does not integrate TypeScript into the build
system yet, so we cannot start converting files to TypeScript and
pushing them to the repo until that final step is complete.
We would like to insert TypeScript into the ESLint configuration, and
because of the way that the current config is organized, that is not
easy to do.
Most files are assumed to be files that are suited for running in a
browser context. This isn't correct, as we should expect most files to
work in a Node context instead. This is because all browser-based files
will be run through a transpiler that is able to make use of
Node-specific variables anyway.
There are a couple of important ways we can categories files which our
ESLint config should be capable of handling well:
* Is the file a script or a module? In other words, does the file run
procedurally or is the file intended to be brought into an existing
file?
* If the file is a module, does it use the CommonJS syntax (`require()`)
or does it use the ES syntax (`import`/`export`)?
When we introduce TypeScript, this set of questions will become:
* Is the file a script or a module?
* If the file is a module, is it a JavaScript module or a TypeScript
module?
* If the file is a JavaScript module, does it use the CommonJS syntax
(`require()`) or does it use the ES syntax (`import`/`export`)?
To represent these divisions, this commit removes global rules — so now
all of the rules are kept in `overrides` for explicitness — and sets up
rules for CommonJS- and ES-module-compatible files that intentionally do
not overlap with each other. This way TypeScript (which has its own set
of rules independent from JavaScript and therefore shouldn't overlap
with the other rules either) can be easily added later.
Finally, this commit splits up the ESLint config into separate files and
adds documentation to each section. This way sets of rules which are
connected to a particular plugin (`jsdoc`, `@babel`, etc.) can be easily
understood instead of being obscured.
ESLint rules have been added to enforce our JSDoc conventions. These
rules were introduced by updating `@metamask/eslint-config` to v9.
Some of the rules have been disabled because the effort to fix all lint
errors was too high. It might be easiest to enable these rules one
directory at a time, or one rule at a time.
Most of the changes in this PR were a result of running
`yarn lint:fix`. There were a handful of manual changes that seemed
obvious and simple to make. Anything beyond that and the rule was left
disabled.
The ESLint config has been updated to v8. The breaking changes are:
* The Prettier rule `quoteProps` has been changed from `consistent` to
`as-needed`, meaning that if one key requires quoting, only that key is
quoted rather than all keys.
* The ESLint rule `no-shadow` has been made more strict. It now
prevents globals from being shadowed as well.
Most of these changes were applied with `yarn lint:fix`. Only the
shadowing changes required manual fixing (shadowing variable names were
either replaced with destructuring or renamed).
The dependency `globalThis` was added to the list of dynamic
dependencies in the build system, where it should have been already.
This was causing `depcheck` to fail because the new lint rules required
removing the one place where `globalThis` had been erroneously imported
previously.
A rule requiring a newline between multiline blocks and expressions has
been disabled temporarily to make this PR smaller and to avoid
introducing conflicts with other PRs.
# Permission System 2.0
## Background
This PR migrates the extension permission system to [the new `PermissionController`](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions).
The original permission system, based on [`rpc-cap`](https://github.com/MetaMask/rpc-cap), introduced [`ZCAP-LD`](https://w3c-ccg.github.io/zcap-ld/)-like permissions to our JSON-RPC stack.
We used it to [implement](https://github.com/MetaMask/metamask-extension/pull/7004) what we called "LoginPerSite" in [version 7.7.0](https://github.com/MetaMask/metamask-extension/releases/tag/v7.7.0) of the extension, which enabled the user to choose which accounts, if any, should be exposed to each dapp.
While that was a worthwhile feature in and of itself, we wanted a permission _system_ in order to enable everything we are going to with Snaps.
Unfortunately, the original permission system was difficult to use, and necessitated the creation of the original `PermissionsController` (note the "s"), which was more or less a wrapper for `rpc-cap`.
With this PR, we shake off the yoke of the original permission system, in favor of the modular, self-contained, ergonomic, and more mature permission system 2.0.
Note that [the `PermissionController` readme](https://github.com/MetaMask/snaps-skunkworks/tree/main/packages/controllers/src/permissions/README.md) explains how the new permission system works.
The `PermissionController` and `SubjectMetadataController` are currently shipped via `@metamask/snap-controllers`. This is a temporary state of affairs, and we'll move them to `@metamask/controllers` once they've landed in prod.
## Changes in Detail
First, the changes in this PR are not as big as they seem. Roughly half of the additions in this PR are fixtures in the test for the new migration (number 68), and a significant portion of the remaining ~2500 lines are due to find-and-replace changes in other test fixtures and UI files.
- The extension `PermissionsController` has been deleted, and completely replaced with the new `PermissionController` from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The original `PermissionsController` "domain metadata" functionality is now managed by the new `SubjectMetadataController`, also from [`@metamask/snap-controllers`](https://www.npmjs.com/package/@metamask/snap-controllers).
- The permission activity and history log controller has been renamed `PermissionLogController` and has its own top-level state key, but is otherwise functionally equivalent to the existing implementation.
- Migration number 68 has been added to account for the new state changes.
- The tests in `app/scripts/controllers/permissions` have been migrated from `mocha` to `jest`.
Reviewers should focus their attention on the following files:
- `app/scripts/`
- `metamask-controller.js`
- This is where most of the integration work for the new `PermissionController` occurs.
Some functions that were internal to the original controller were moved here.
- `controllers/permissions/`
- `selectors.js`
- These selectors are for `ControllerMessenger` selector subscriptions. The actual subscriptions occur in `metamask-controller.js`. See the `ControllerMessenger` implementation for details.
- `specifications.js`
- The caveat and permission specifications are required by the new `PermissionController`, and are used to specify the `eth_accounts` permission and its JSON-RPC method implementation.
See the `PermissionController` readme for details.
- `migrations/068.js`
- The new state should be cross-referenced with the controllers that manage it.
The accompanying tests should also be thoroughly reviewed.
Some files may appear new but have just moved and/or been renamed:
- `app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js`
- This was previously implemented in `controllers/permissions/permissionsMethodMiddleware.js`.
- `test/mocks/permissions.js`
- A truncated version of `test/mocks/permission-controller.js`.
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
This PR adds one LavaMoat background script policy or each build type. It also renames the build system policy directory from `node` to `build-system` to make its purpose more clear. Each build type has the original `policy-override.json` for `main` builds. The `.prettierignore` file has been updated to match the locations of the new auto-generated policy files.
We need to maintain separate policies for each build type because each type will produce different bundles with different internal and external modules.
Co-authored-by: Mark Stacey <markjstacey@gmail.com>