├── .editorconfig ├── .eslintrc.js ├── .gitattributes ├── .github ├── CODEOWNERS ├── dependabot.yml └── workflows │ ├── build-lint-test.yml │ ├── create-release-pr.yml │ ├── main.yml │ ├── publish-environment.yml │ ├── publish-preview.yml │ └── publish-release.yml ├── .gitignore ├── .nvmrc ├── .prettierignore ├── .prettierrc.js ├── .swcrc.build.json ├── .yarn ├── patches │ ├── @babel-core-npm-7.21.0-fb3817b0e5.patch │ ├── @lavamoat-lavapack-npm-5.1.2-67a55c51e2.patch │ ├── @types-glob-npm-7.1.4-d45247eaa2.patch │ ├── @types-mocha-npm-10.0.1-7c94e9e170.patch │ ├── clet-npm-1.0.1-8523231bdc.patch │ ├── inline-source-map-npm-0.6.2-96902459a0.patch │ ├── jest-fetch-mock-npm-3.0.3-ac072ca8af.patch │ ├── lavamoat-browserify-npm-15.6.0-e22edafc36.patch │ └── luxon-npm-3.3.0-bdbae9bfd5.patch ├── plugins │ ├── @yarnpkg │ │ ├── plugin-allow-scripts.cjs │ │ ├── plugin-constraints.cjs │ │ └── plugin-workspace-tools.cjs │ └── local │ │ └── plugin-workspaces-filter.js └── releases │ └── yarn-3.4.1.cjs ├── .yarnrc.yml ├── LICENSE ├── README.md ├── constraints.pro ├── jest.config.base.js ├── package.json ├── packages ├── create-snap │ ├── .eslintrc.js │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── __mocks__ │ │ │ └── fs.ts │ │ ├── builders.ts │ │ ├── cli.test.ts │ │ ├── cli.ts │ │ ├── cmds │ │ │ ├── index.ts │ │ │ └── init │ │ │ │ ├── index.ts │ │ │ │ ├── init.test.ts │ │ │ │ ├── initHandler.test.ts │ │ │ │ ├── initHandler.ts │ │ │ │ ├── initUtils.test.ts │ │ │ │ └── initUtils.ts │ │ ├── main.test.ts │ │ ├── main.ts │ │ ├── test-utils │ │ │ ├── fs.ts │ │ │ └── index.ts │ │ └── types │ │ │ ├── snaps-cli.d.ts │ │ │ └── yargs.d.ts │ ├── test │ │ └── setup.js │ ├── tsconfig.build.json │ └── tsconfig.json ├── examples │ ├── .eslintrc.js │ ├── CHANGELOG.md │ ├── LICENSE.APACHE2 │ ├── LICENSE.MIT0 │ ├── README.md │ ├── package.json │ ├── packages │ │ ├── bip32 │ │ │ ├── .eslintrc.js │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── images │ │ │ │ └── icon.svg │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── snap.config.js │ │ │ ├── snap.manifest.json │ │ │ ├── src │ │ │ │ ├── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ └── utils.ts │ │ │ └── tsconfig.json │ │ ├── bip44 │ │ │ ├── .eslintrc.js │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── images │ │ │ │ └── icon.svg │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── snap.config.js │ │ │ ├── snap.manifest.json │ │ │ ├── src │ │ │ │ ├── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ └── utils.ts │ │ │ └── tsconfig.json │ │ ├── browserify-plugin │ │ │ ├── .eslintrc.js │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── babel.config.json │ │ │ ├── images │ │ │ │ └── icon.svg │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── scripts │ │ │ │ └── build.ts │ │ │ ├── snap.manifest.json │ │ │ ├── src │ │ │ │ ├── index.test.ts │ │ │ │ └── index.ts │ │ │ └── tsconfig.json │ │ ├── cronjobs │ │ │ ├── .eslintrc.js │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── images │ │ │ │ └── icon.svg │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── snap.config.js │ │ │ ├── snap.manifest.json │ │ │ ├── src │ │ │ │ ├── index.test.ts │ │ │ │ └── index.ts │ │ │ └── tsconfig.json │ │ ├── dialogs │ │ │ ├── .eslintrc.js │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── images │ │ │ │ └── icon.svg │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── snap.config.js │ │ │ ├── snap.manifest.json │ │ │ ├── src │ │ │ │ ├── index.test.ts │ │ │ │ └── index.ts │ │ │ └── tsconfig.json │ │ ├── errors │ │ │ ├── .eslintrc.js │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── images │ │ │ │ └── icon.svg │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── snap.config.js │ │ │ ├── snap.manifest.json │ │ │ ├── src │ │ │ │ ├── index.test.ts │ │ │ │ └── index.ts │ │ │ └── tsconfig.json │ │ ├── ethereum-provider │ │ │ ├── .eslintrc.js │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── images │ │ │ │ └── icon.svg │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── snap.config.js │ │ │ ├── snap.manifest.json │ │ │ ├── src │ │ │ │ ├── index.test.ts │ │ │ │ └── index.ts │ │ │ └── tsconfig.json │ │ ├── ethers-js │ │ │ ├── .eslintrc.js │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── images │ │ │ │ └── icon.svg │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── snap.config.js │ │ │ ├── snap.manifest.json │ │ │ ├── src │ │ │ │ ├── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ └── utils.ts │ │ │ └── tsconfig.json │ │ ├── get-entropy │ │ │ ├── .eslintrc.js │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── images │ │ │ │ └── icon.svg │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── snap.config.js │ │ │ ├── snap.manifest.json │ │ │ ├── src │ │ │ │ ├── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ └── utils.ts │ │ │ └── tsconfig.json │ │ ├── invoke-snap │ │ │ ├── .eslintrc.js │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── package.json │ │ │ ├── packages │ │ │ │ ├── consumer-signer │ │ │ │ │ ├── .eslintrc.js │ │ │ │ │ ├── CHANGELOG.md │ │ │ │ │ ├── LICENSE.APACHE2 │ │ │ │ │ ├── LICENSE.MIT0 │ │ │ │ │ ├── README.md │ │ │ │ │ ├── images │ │ │ │ │ │ └── icon.svg │ │ │ │ │ ├── jest.config.js │ │ │ │ │ ├── package.json │ │ │ │ │ ├── snap.config.js │ │ │ │ │ ├── snap.manifest.json │ │ │ │ │ ├── src │ │ │ │ │ │ ├── index.test.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── types.ts │ │ │ │ │ └── tsconfig.json │ │ │ │ └── core-signer │ │ │ │ │ ├── .eslintrc.js │ │ │ │ │ ├── CHANGELOG.md │ │ │ │ │ ├── LICENSE.APACHE2 │ │ │ │ │ ├── LICENSE.MIT0 │ │ │ │ │ ├── README.md │ │ │ │ │ ├── images │ │ │ │ │ └── icon.svg │ │ │ │ │ ├── jest.config.js │ │ │ │ │ ├── package.json │ │ │ │ │ ├── snap.config.js │ │ │ │ │ ├── snap.manifest.json │ │ │ │ │ ├── src │ │ │ │ │ ├── index.test.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── utils.ts │ │ │ │ │ └── tsconfig.json │ │ │ └── tsconfig.json │ │ ├── json-rpc │ │ │ ├── .eslintrc.js │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── images │ │ │ │ └── icon.svg │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── snap.config.js │ │ │ ├── snap.manifest.json │ │ │ ├── src │ │ │ │ ├── index.test.ts │ │ │ │ └── index.ts │ │ │ └── tsconfig.json │ │ ├── manage-state │ │ │ ├── .eslintrc.js │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── images │ │ │ │ └── icon.svg │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── snap.config.js │ │ │ ├── snap.manifest.json │ │ │ ├── src │ │ │ │ ├── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ └── utils.ts │ │ │ └── tsconfig.json │ │ ├── network-access │ │ │ ├── .eslintrc.js │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── images │ │ │ │ └── icon.svg │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── snap.config.js │ │ │ ├── snap.manifest.json │ │ │ ├── src │ │ │ │ ├── constants.ts │ │ │ │ ├── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ │ └── tsconfig.json │ │ ├── notifications │ │ │ ├── .eslintrc.js │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── images │ │ │ │ └── icon.svg │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── snap.config.js │ │ │ ├── snap.manifest.json │ │ │ ├── src │ │ │ │ ├── index.test.ts │ │ │ │ └── index.ts │ │ │ └── tsconfig.json │ │ ├── rollup-plugin │ │ │ ├── .eslintrc.js │ │ │ ├── .gitignore │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── babel.config.json │ │ │ ├── images │ │ │ │ └── icon.svg │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── rollup.config.js │ │ │ ├── snap.manifest.json │ │ │ ├── src │ │ │ │ ├── index.test.ts │ │ │ │ └── index.ts │ │ │ └── tsconfig.json │ │ ├── transaction-insights │ │ │ ├── .eslintrc.js │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── images │ │ │ │ └── icon.svg │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── snap.config.js │ │ │ ├── snap.manifest.json │ │ │ ├── src │ │ │ │ ├── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ └── utils.ts │ │ │ └── tsconfig.json │ │ ├── wasm │ │ │ ├── .eslintrc.js │ │ │ ├── .gitignore │ │ │ ├── .swcrc │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── asconfig.json │ │ │ ├── assembly │ │ │ │ └── program.ts │ │ │ ├── images │ │ │ │ └── icon.svg │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── snap.manifest.json │ │ │ ├── src │ │ │ │ ├── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ └── types.d.ts │ │ │ ├── tsconfig.json │ │ │ └── webpack.config.ts │ │ └── webpack-plugin │ │ │ ├── .eslintrc.js │ │ │ ├── .swcrc │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE.APACHE2 │ │ │ ├── LICENSE.MIT0 │ │ │ ├── README.md │ │ │ ├── images │ │ │ └── icon.svg │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── snap.manifest.json │ │ │ ├── src │ │ │ ├── index.test.ts │ │ │ └── index.ts │ │ │ ├── tsconfig.json │ │ │ └── webpack.config.ts │ └── tsconfig.json ├── rpc-methods │ ├── .eslintrc.js │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── __fixtures__ │ │ │ ├── entropy.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── permitted │ │ │ ├── common │ │ │ │ └── snapInstallation.ts │ │ │ ├── getSnaps.ts │ │ │ ├── handlers.ts │ │ │ ├── index.ts │ │ │ ├── invokeSnapSugar.test.ts │ │ │ ├── invokeSnapSugar.ts │ │ │ ├── middleware.test.ts │ │ │ ├── middleware.ts │ │ │ ├── requestSnaps.test.ts │ │ │ └── requestSnaps.ts │ │ ├── request.test.ts │ │ ├── request.ts │ │ ├── restricted │ │ │ ├── caveats │ │ │ │ ├── index.ts │ │ │ │ ├── permittedCoinTypes.test.ts │ │ │ │ ├── permittedCoinTypes.ts │ │ │ │ ├── permittedDerivationPaths.test.ts │ │ │ │ ├── permittedDerivationPaths.ts │ │ │ │ ├── snapIds.test.ts │ │ │ │ └── snapIds.ts │ │ │ ├── dialog.test.ts │ │ │ ├── dialog.ts │ │ │ ├── getBip32Entropy.test.ts │ │ │ ├── getBip32Entropy.ts │ │ │ ├── getBip32PublicKey.test.ts │ │ │ ├── getBip32PublicKey.ts │ │ │ ├── getBip44Entropy.test.ts │ │ │ ├── getBip44Entropy.ts │ │ │ ├── getEntropy.test.ts │ │ │ ├── getEntropy.ts │ │ │ ├── index.ts │ │ │ ├── invokeSnap.test.ts │ │ │ ├── invokeSnap.ts │ │ │ ├── manageState.test.ts │ │ │ ├── manageState.ts │ │ │ ├── notify.test.ts │ │ │ └── notify.ts │ │ ├── utils.test.ts │ │ └── utils.ts │ ├── tsconfig.build.json │ └── tsconfig.json ├── snaps-browserify-plugin │ ├── .eslintrc.js │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── __mocks__ │ │ │ └── fs.ts │ │ ├── __snapshots__ │ │ │ └── plugin.test.ts.snap │ │ ├── index.ts │ │ ├── plugin.test.ts │ │ └── plugin.ts │ ├── tsconfig.build.json │ └── tsconfig.json ├── snaps-cli │ ├── .eslintrc.js │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── babel.config.js │ ├── jest.config.js │ ├── package.json │ ├── scripts │ │ └── updateReadme.js │ ├── src │ │ ├── __mocks__ │ │ │ └── fs.ts │ │ ├── builders.ts │ │ ├── cli.test.ts │ │ ├── cli.ts │ │ ├── cmds │ │ │ ├── build │ │ │ │ ├── build.e2e.test.ts │ │ │ │ ├── build.test.ts │ │ │ │ ├── buildHandler.ts │ │ │ │ ├── bundle.test.ts │ │ │ │ ├── bundle.ts │ │ │ │ ├── index.ts │ │ │ │ ├── utils.test.ts │ │ │ │ └── utils.ts │ │ │ ├── eval │ │ │ │ ├── __test__ │ │ │ │ │ ├── eval-2.js │ │ │ │ │ └── eval.js │ │ │ │ ├── eval.e2e.test.ts │ │ │ │ ├── evalHandler.test.ts │ │ │ │ ├── evalHandler.ts │ │ │ │ ├── index.test.ts │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── init │ │ │ │ └── init.e2e.test.ts │ │ │ ├── manifest │ │ │ │ ├── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── manifest.e2e.test.ts │ │ │ │ ├── manifestHandler.test.ts │ │ │ │ └── manifestHandler.ts │ │ │ ├── serve │ │ │ │ ├── index.ts │ │ │ │ ├── serve.e2e.test.ts │ │ │ │ ├── serve.test.ts │ │ │ │ ├── serveHandler.ts │ │ │ │ ├── serveUtils.test.ts │ │ │ │ └── serveUtils.ts │ │ │ └── watch │ │ │ │ ├── index.ts │ │ │ │ ├── watch.e2e.test.ts │ │ │ │ ├── watchHandler.test.ts │ │ │ │ └── watchHandler.ts │ │ ├── index.ts │ │ ├── main.test.ts │ │ ├── main.ts │ │ ├── test-utils │ │ │ ├── e2e.ts │ │ │ ├── fs.ts │ │ │ └── index.ts │ │ ├── types │ │ │ ├── snaps-cli.d.ts │ │ │ └── yargs.d.ts │ │ └── utils │ │ │ ├── index.ts │ │ │ ├── misc.test.ts │ │ │ ├── misc.ts │ │ │ ├── snap-config.test.ts │ │ │ └── snap-config.ts │ ├── test │ │ ├── setup.js │ │ └── snap │ │ │ ├── README.md │ │ │ ├── images │ │ │ └── icon.svg │ │ │ ├── package.json │ │ │ ├── snap.config.js │ │ │ ├── snap.manifest.json │ │ │ └── src │ │ │ └── index.ts │ ├── tsconfig.build.json │ └── tsconfig.json ├── snaps-controllers │ ├── .eslintrc.js │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── coverage.json │ ├── jest.config.js │ ├── package.json │ ├── scripts │ │ ├── coverage.ts │ │ └── generate-fixtures.sh │ ├── src │ │ ├── cronjob │ │ │ ├── CronjobController.test.ts │ │ │ ├── CronjobController.ts │ │ │ └── index.ts │ │ ├── fsm.test.ts │ │ ├── fsm.ts │ │ ├── index.ts │ │ ├── logging.ts │ │ ├── services │ │ │ ├── AbstractExecutionService.test.ts │ │ │ ├── AbstractExecutionService.ts │ │ │ ├── ExecutionService.ts │ │ │ ├── ProxyPostMessageStream.test.ts │ │ │ ├── ProxyPostMessageStream.ts │ │ │ ├── browser.test.ts │ │ │ ├── browser.ts │ │ │ ├── iframe │ │ │ │ ├── IframeExecutionService.test.browser.ts │ │ │ │ ├── IframeExecutionService.ts │ │ │ │ ├── index.ts │ │ │ │ └── test │ │ │ │ │ └── index.html │ │ │ ├── index.ts │ │ │ ├── node │ │ │ │ ├── NodeProcessExecutionService.test.ts │ │ │ │ ├── NodeProcessExecutionService.ts │ │ │ │ ├── NodeThreadExecutionService.test.ts │ │ │ │ ├── NodeThreadExecutionService.ts │ │ │ │ └── index.ts │ │ │ ├── offscreen │ │ │ │ ├── OffscreenExecutionService.test.ts │ │ │ │ ├── OffscreenExecutionService.ts │ │ │ │ └── index.ts │ │ │ └── webworker │ │ │ │ ├── WebWorkerExecutionService.test.browser.ts │ │ │ │ ├── WebWorkerExecutionService.ts │ │ │ │ └── index.ts │ │ ├── snaps │ │ │ ├── RequestQueue.test.ts │ │ │ ├── RequestQueue.ts │ │ │ ├── SnapController.test.ts │ │ │ ├── SnapController.ts │ │ │ ├── Timer.test.ts │ │ │ ├── Timer.ts │ │ │ ├── endowments │ │ │ │ ├── cronjob.test.ts │ │ │ │ ├── cronjob.ts │ │ │ │ ├── enum.ts │ │ │ │ ├── ethereum-provider.test.ts │ │ │ │ ├── ethereum-provider.ts │ │ │ │ ├── index.ts │ │ │ │ ├── long-running.test.ts │ │ │ │ ├── long-running.ts │ │ │ │ ├── network-access.test.ts │ │ │ │ ├── network-access.ts │ │ │ │ ├── rpc.test.ts │ │ │ │ ├── rpc.ts │ │ │ │ ├── transaction-insight.test.ts │ │ │ │ ├── transaction-insight.ts │ │ │ │ ├── web-assembly.test.ts │ │ │ │ └── web-assembly.ts │ │ │ ├── index.ts │ │ │ ├── location │ │ │ │ ├── http.test.ts │ │ │ │ ├── http.ts │ │ │ │ ├── index.ts │ │ │ │ ├── local.test.ts │ │ │ │ ├── local.ts │ │ │ │ ├── location.test.ts │ │ │ │ ├── location.ts │ │ │ │ ├── npm.test.ts │ │ │ │ └── npm.ts │ │ │ ├── permission.test.ts │ │ │ ├── permissions.ts │ │ │ ├── registry │ │ │ │ ├── index.ts │ │ │ │ ├── json.test.ts │ │ │ │ ├── json.ts │ │ │ │ └── registry.ts │ │ │ └── selectors.ts │ │ ├── test-utils │ │ │ ├── controller.ts │ │ │ ├── cronjob.ts │ │ │ ├── execution-environment.ts │ │ │ ├── index.ts │ │ │ ├── location.ts │ │ │ ├── mock.ts │ │ │ ├── registry.ts │ │ │ ├── service.ts │ │ │ └── sleep.ts │ │ ├── utils.test.ts │ │ └── utils.ts │ ├── tsconfig.build.json │ ├── tsconfig.json │ ├── tsconfig.local.json │ └── wdio.config.ts ├── snaps-execution-environments │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── coverage.json │ ├── jest.config.js │ ├── jest.environment.js │ ├── lavamoat │ │ ├── browserify │ │ │ ├── iframe │ │ │ │ └── policy.json │ │ │ ├── node-process │ │ │ │ └── policy.json │ │ │ ├── node-thread │ │ │ │ └── policy.json │ │ │ ├── offscreen │ │ │ │ └── policy.json │ │ │ ├── policy-override.json │ │ │ ├── worker-executor │ │ │ │ └── policy.json │ │ │ └── worker-pool │ │ │ │ └── policy.json │ │ └── build-system │ │ │ ├── policy-override.json │ │ │ └── policy.json │ ├── package.json │ ├── scripts │ │ ├── build.js │ │ ├── coverage.ts │ │ └── start.js │ ├── src │ │ ├── common │ │ │ ├── BaseSnapExecutor.test.browser.ts │ │ │ ├── BaseSnapExecutor.ts │ │ │ ├── commands.test.ts │ │ │ ├── commands.ts │ │ │ ├── endowments │ │ │ │ ├── commonEndowmentFactory.ts │ │ │ │ ├── console.test.ts │ │ │ │ ├── console.ts │ │ │ │ ├── crypto.test.ts │ │ │ │ ├── crypto.ts │ │ │ │ ├── date.test.ts │ │ │ │ ├── date.ts │ │ │ │ ├── endowments.test.browser.ts │ │ │ │ ├── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interval.test.ts │ │ │ │ ├── interval.ts │ │ │ │ ├── math.test.ts │ │ │ │ ├── math.ts │ │ │ │ ├── network.test.ts │ │ │ │ ├── network.ts │ │ │ │ ├── textDecoder.ts │ │ │ │ ├── textEncoder.ts │ │ │ │ ├── timeout.test.ts │ │ │ │ └── timeout.ts │ │ │ ├── globalEvents.test.ts │ │ │ ├── globalEvents.ts │ │ │ ├── globalObject.test.ts │ │ │ ├── globalObject.ts │ │ │ ├── lockdown │ │ │ │ ├── lockdown-events.test.browser.ts │ │ │ │ ├── lockdown-events.ts │ │ │ │ ├── lockdown-more.ts │ │ │ │ └── lockdown.ts │ │ │ ├── sortParams.test.ts │ │ │ ├── sortParams.ts │ │ │ ├── test-utils │ │ │ │ ├── endowments.ts │ │ │ │ ├── executor.ts │ │ │ │ ├── hardening.ts │ │ │ │ └── logger.ts │ │ │ ├── utils.test.ts │ │ │ ├── utils.ts │ │ │ ├── validation.test.ts │ │ │ └── validation.ts │ │ ├── globals.d.ts │ │ ├── iframe │ │ │ ├── IFrameSnapExecutor.test.browser.ts │ │ │ ├── IFrameSnapExecutor.ts │ │ │ └── index.ts │ │ ├── logging.ts │ │ ├── node-process │ │ │ ├── ChildProcessSnapExecutor.test.ts │ │ │ ├── ChildProcessSnapExecutor.ts │ │ │ └── index.ts │ │ ├── node-thread │ │ │ ├── ThreadSnapExecutor.test.ts │ │ │ ├── ThreadSnapExecutor.ts │ │ │ └── index.ts │ │ ├── offscreen │ │ │ ├── OffscreenSnapExecutor.test.browser.ts │ │ │ ├── OffscreenSnapExecutor.ts │ │ │ └── index.ts │ │ ├── openrpc.json │ │ └── webworker │ │ │ ├── executor │ │ │ ├── WebWorkerSnapExecutor.test.browser.ts │ │ │ ├── WebWorkerSnapExecutor.ts │ │ │ └── index.ts │ │ │ └── pool │ │ │ ├── WebWorkerPool.test.browser.ts │ │ │ ├── WebWorkerPool.ts │ │ │ └── index.ts │ ├── tsconfig.build.json │ ├── tsconfig.json │ └── wdio.config.ts ├── snaps-jest │ ├── .eslintrc.js │ ├── .gitignore │ ├── CHANGELOG.md │ ├── README.md │ ├── jest-preset.js │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── environment.ts │ │ ├── helpers.ts │ │ ├── index.ts │ │ ├── internals │ │ │ ├── environment.ts │ │ │ ├── index.ts │ │ │ ├── interface.ts │ │ │ ├── logger.ts │ │ │ ├── network.ts │ │ │ ├── request.ts │ │ │ ├── server.ts │ │ │ ├── structs.ts │ │ │ ├── types.ts │ │ │ └── wait-for.ts │ │ ├── matchers.ts │ │ ├── options.ts │ │ ├── setup.ts │ │ └── types.ts │ ├── tsconfig.build.json │ └── tsconfig.json ├── snaps-rollup-plugin │ ├── .eslintrc.js │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── __fixtures__ │ │ │ └── source-map.ts │ │ ├── __mocks__ │ │ │ └── fs.ts │ │ ├── index.ts │ │ ├── plugin.test.ts │ │ └── plugin.ts │ ├── tsconfig.build.json │ └── tsconfig.json ├── snaps-simulator │ ├── .eslintrc.js │ ├── .gitignore │ ├── .swcrc │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── babel.config.js │ ├── jest.config.js │ ├── jest.environment.js │ ├── jest.setup.js │ ├── package.json │ ├── src │ │ ├── App.test.tsx │ │ ├── App.tsx │ │ ├── api.ts │ │ ├── assets │ │ │ ├── favicon.svg │ │ │ ├── file-mock.ts │ │ │ ├── fonts │ │ │ │ ├── EuclidCircularB-Bold.woff2 │ │ │ │ ├── EuclidCircularB-Regular.woff2 │ │ │ │ ├── IBMPlexMono-Regular.woff2 │ │ │ │ └── fonts.css │ │ │ ├── icons │ │ │ │ ├── alert.svg │ │ │ │ ├── arrow-down.svg │ │ │ │ ├── arrow-right.svg │ │ │ │ ├── arrow-top-right.svg │ │ │ │ ├── computer.svg │ │ │ │ ├── configuration-dark.svg │ │ │ │ ├── configuration.svg │ │ │ │ ├── copied.svg │ │ │ │ ├── copy.svg │ │ │ │ ├── copyable.svg │ │ │ │ ├── cronjob.svg │ │ │ │ ├── cross-dark.svg │ │ │ │ ├── cross.svg │ │ │ │ ├── dark-arrow-top-right.svg │ │ │ │ ├── divider.svg │ │ │ │ ├── dot.svg │ │ │ │ ├── drag.svg │ │ │ │ ├── error-triangle.svg │ │ │ │ ├── github-dark.svg │ │ │ │ ├── github.svg │ │ │ │ ├── heading.svg │ │ │ │ ├── insights.svg │ │ │ │ ├── json-rpc.svg │ │ │ │ ├── manifest.svg │ │ │ │ ├── moon.svg │ │ │ │ ├── panel.svg │ │ │ │ ├── play-error.svg │ │ │ │ ├── play-muted.svg │ │ │ │ ├── play-success.svg │ │ │ │ ├── play.svg │ │ │ │ ├── snap.svg │ │ │ │ ├── text-bubble.svg │ │ │ │ ├── text.svg │ │ │ │ └── ui.svg │ │ │ ├── logo-dark.svg │ │ │ └── logo.svg │ │ ├── components │ │ │ ├── Author.test.tsx │ │ │ ├── Author.tsx │ │ │ ├── Delineator.tsx │ │ │ ├── Editor.tsx │ │ │ ├── Icon.test.tsx │ │ │ ├── Icon.tsx │ │ │ ├── Link.test.tsx │ │ │ ├── Link.tsx │ │ │ ├── Logo.test.tsx │ │ │ ├── Logo.tsx │ │ │ ├── Prefill.test.tsx │ │ │ ├── Prefill.tsx │ │ │ ├── Root.tsx │ │ │ ├── SnapIcon.test.tsx │ │ │ ├── SnapIcon.tsx │ │ │ ├── TestConditional.tsx │ │ │ ├── Window.test.tsx │ │ │ ├── Window.tsx │ │ │ ├── dialogs │ │ │ │ ├── AlertDialog.test.tsx │ │ │ │ ├── AlertDialog.tsx │ │ │ │ ├── ConfirmationDialog.test.tsx │ │ │ │ ├── ConfirmationDialog.tsx │ │ │ │ ├── PromptDialog.test.tsx │ │ │ │ ├── PromptDialog.tsx │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ ├── entry.tsx │ │ ├── features │ │ │ ├── builder │ │ │ │ ├── Builder.tsx │ │ │ │ ├── components │ │ │ │ │ ├── BaseNode.tsx │ │ │ │ │ ├── EditableNode.tsx │ │ │ │ │ ├── Node.tsx │ │ │ │ │ ├── NodeRenderer.tsx │ │ │ │ │ ├── NodeTree.tsx │ │ │ │ │ ├── Start.tsx │ │ │ │ │ ├── TemplateComponent.tsx │ │ │ │ │ ├── TemplateComponentList.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ ├── utils.test.ts │ │ │ │ └── utils.ts │ │ │ ├── configuration │ │ │ │ ├── Configuration.test.tsx │ │ │ │ ├── Configuration.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── slice.test.ts │ │ │ │ └── slice.ts │ │ │ ├── console │ │ │ │ ├── Console.tsx │ │ │ │ ├── ConsoleContent.tsx │ │ │ │ ├── index.ts │ │ │ │ └── slice.ts │ │ │ ├── handlers │ │ │ │ ├── components │ │ │ │ │ ├── Handler.test.tsx │ │ │ │ │ ├── Handler.tsx │ │ │ │ │ ├── History.test.tsx │ │ │ │ │ ├── History.tsx │ │ │ │ │ ├── HistoryItem.test.tsx │ │ │ │ │ ├── HistoryItem.tsx │ │ │ │ │ ├── PlayButton.tsx │ │ │ │ │ ├── ResetTab.tsx │ │ │ │ │ ├── ResetUserInterfaceTab.tsx │ │ │ │ │ ├── Response.test.tsx │ │ │ │ │ ├── Response.tsx │ │ │ │ │ ├── UserInterface.test.tsx │ │ │ │ │ ├── UserInterface.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── cronjobs │ │ │ │ │ ├── Cronjobs.test.tsx │ │ │ │ │ ├── Cronjobs.tsx │ │ │ │ │ ├── components │ │ │ │ │ │ ├── CronjobPrefill.test.tsx │ │ │ │ │ │ ├── CronjobPrefill.tsx │ │ │ │ │ │ ├── CronjobPrefills.test.tsx │ │ │ │ │ │ ├── CronjobPrefills.tsx │ │ │ │ │ │ ├── Request.test.tsx │ │ │ │ │ │ ├── Request.tsx │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── slice.test.ts │ │ │ │ │ └── slice.ts │ │ │ │ ├── index.ts │ │ │ │ ├── json-rpc │ │ │ │ │ ├── JsonRpc.test.tsx │ │ │ │ │ ├── JsonRpc.tsx │ │ │ │ │ ├── components │ │ │ │ │ │ ├── Request.tsx │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── schema.ts │ │ │ │ │ ├── slice.test.ts │ │ │ │ │ └── slice.ts │ │ │ │ ├── slice.ts │ │ │ │ └── transactions │ │ │ │ │ ├── Transactions.test.tsx │ │ │ │ │ ├── Transactions.tsx │ │ │ │ │ ├── components │ │ │ │ │ ├── Request.tsx │ │ │ │ │ ├── TransactionPrefill.test.tsx │ │ │ │ │ ├── TransactionPrefill.tsx │ │ │ │ │ ├── TransactionPrefills.test.tsx │ │ │ │ │ ├── TransactionPrefills.tsx │ │ │ │ │ └── index.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── presets.ts │ │ │ │ │ ├── slice.test.ts │ │ │ │ │ ├── slice.ts │ │ │ │ │ ├── utils.test.ts │ │ │ │ │ └── utils.ts │ │ │ ├── index.library.ts │ │ │ ├── index.ts │ │ │ ├── layout │ │ │ │ ├── Layout.tsx │ │ │ │ ├── components │ │ │ │ │ ├── Header.test.tsx │ │ │ │ │ ├── Header.tsx │ │ │ │ │ ├── Sidebar.test.tsx │ │ │ │ │ ├── Sidebar.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ ├── manifest │ │ │ │ ├── Manifest.test.tsx │ │ │ │ ├── Manifest.tsx │ │ │ │ ├── components │ │ │ │ │ ├── Item.test.tsx │ │ │ │ │ ├── Item.tsx │ │ │ │ │ ├── Validation.test.tsx │ │ │ │ │ ├── Validation.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ ├── sagas.test.ts │ │ │ │ ├── sagas.ts │ │ │ │ ├── slice.test.ts │ │ │ │ ├── slice.ts │ │ │ │ └── validators.ts │ │ │ ├── navigation │ │ │ │ ├── Navigation.test.tsx │ │ │ │ ├── Navigation.tsx │ │ │ │ ├── components │ │ │ │ │ ├── Bottom.test.tsx │ │ │ │ │ ├── Bottom.tsx │ │ │ │ │ ├── Item.test.tsx │ │ │ │ │ ├── Item.tsx │ │ │ │ │ ├── ManifestStatusIndicator.tsx │ │ │ │ │ ├── NavigationTag.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ └── items.ts │ │ │ ├── notifications │ │ │ │ ├── Notifications.test.tsx │ │ │ │ ├── Notifications.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── slice.test.ts │ │ │ │ └── slice.ts │ │ │ ├── polling │ │ │ │ ├── index.ts │ │ │ │ ├── sagas.test.ts │ │ │ │ └── sagas.ts │ │ │ ├── renderer │ │ │ │ ├── Renderer.tsx │ │ │ │ ├── components │ │ │ │ │ ├── Copyable.tsx │ │ │ │ │ ├── Divider.tsx │ │ │ │ │ ├── Heading.tsx │ │ │ │ │ ├── Panel.tsx │ │ │ │ │ ├── Spinner.tsx │ │ │ │ │ ├── Text.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ ├── simulation │ │ │ │ ├── constants.ts │ │ │ │ ├── hooks.test.ts │ │ │ │ ├── hooks.ts │ │ │ │ ├── index.library.ts │ │ │ │ ├── index.ts │ │ │ │ ├── middleware.test.ts │ │ │ │ ├── middleware.ts │ │ │ │ ├── sagas.test.ts │ │ │ │ ├── sagas.ts │ │ │ │ ├── slice.test.ts │ │ │ │ ├── slice.ts │ │ │ │ ├── snap-permissions.ts │ │ │ │ └── test │ │ │ │ │ ├── mockExecutionService.ts │ │ │ │ │ ├── mockManifest.ts │ │ │ │ │ └── mockSnap.ts │ │ │ └── status │ │ │ │ ├── StatusIndicator.test.tsx │ │ │ │ ├── StatusIndicator.tsx │ │ │ │ └── index.ts │ │ ├── hooks │ │ │ ├── index.ts │ │ │ ├── useDispatch.ts │ │ │ ├── useHandler.tsx │ │ │ └── useSelector.ts │ │ ├── index.html │ │ ├── index.ts │ │ ├── routes.tsx │ │ ├── store │ │ │ ├── index.library.ts │ │ │ ├── index.ts │ │ │ ├── middleware.ts │ │ │ ├── reducer.ts │ │ │ ├── sagas.ts │ │ │ └── store.ts │ │ ├── stub.ts │ │ ├── theme.ts │ │ ├── types.d.ts │ │ ├── types │ │ │ └── vendor │ │ │ │ └── offscreen.d.ts │ │ └── utils │ │ │ ├── environment.ts │ │ │ ├── index.ts │ │ │ └── render.tsx │ ├── tsconfig.build.json │ ├── tsconfig.json │ └── webpack.config.ts ├── snaps-types │ ├── .eslintrc.js │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ │ ├── global.ts │ │ ├── index.ts │ │ └── types.ts │ ├── tsconfig.build.json │ └── tsconfig.json ├── snaps-ui │ ├── .eslintrc.js │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── builder.test.ts │ │ ├── builder.ts │ │ ├── index.ts │ │ ├── nodes.ts │ │ ├── validation.test.ts │ │ └── validation.ts │ ├── tsconfig.build.json │ └── tsconfig.json ├── snaps-utils │ ├── .eslintrc.js │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── coverage.json │ ├── jest.config.js │ ├── package.json │ ├── scripts │ │ └── coverage.ts │ ├── src │ │ ├── __mocks__ │ │ │ ├── fs.ts │ │ │ └── fs │ │ │ │ └── promises.ts │ │ ├── array.ts │ │ ├── caveats.test.ts │ │ ├── caveats.ts │ │ ├── checksum.test.ts │ │ ├── checksum.ts │ │ ├── cronjob.test.ts │ │ ├── cronjob.ts │ │ ├── deep-clone.ts │ │ ├── default-endowments.ts │ │ ├── entropy.ts │ │ ├── enum.test.ts │ │ ├── enum.ts │ │ ├── eval-worker.js │ │ ├── eval-worker.ts │ │ ├── eval.test.ts │ │ ├── eval.ts │ │ ├── fs.test.ts │ │ ├── fs.ts │ │ ├── handlers.ts │ │ ├── icon.test.ts │ │ ├── icon.ts │ │ ├── iframe.test.browser.ts │ │ ├── iframe.ts │ │ ├── index.browser.ts │ │ ├── index.executionenv.ts │ │ ├── index.ts │ │ ├── json-rpc.test.ts │ │ ├── json-rpc.ts │ │ ├── json.test.ts │ │ ├── json.ts │ │ ├── logging.test.ts │ │ ├── logging.ts │ │ ├── manifest │ │ │ ├── index.browser.ts │ │ │ ├── index.ts │ │ │ ├── manifest.test.ts │ │ │ ├── manifest.ts │ │ │ ├── validation.test.ts │ │ │ └── validation.ts │ │ ├── mock.test.ts │ │ ├── mock.ts │ │ ├── namespace.test.ts │ │ ├── namespace.ts │ │ ├── npm.ts │ │ ├── path.test.ts │ │ ├── path.ts │ │ ├── post-process.test.ts │ │ ├── post-process.ts │ │ ├── snaps.test.ts │ │ ├── snaps.ts │ │ ├── test-utils │ │ │ ├── common.ts │ │ │ ├── controller.ts │ │ │ ├── index.ts │ │ │ ├── manifest.ts │ │ │ ├── sleep.ts │ │ │ ├── snap.ts │ │ │ ├── spy.ts │ │ │ └── stream.ts │ │ ├── types.test.ts │ │ ├── types.ts │ │ ├── validation.test.ts │ │ ├── validation.ts │ │ ├── versions.test.ts │ │ ├── versions.ts │ │ └── virtual-file │ │ │ ├── VirtualFile.test.ts │ │ │ ├── VirtualFile.ts │ │ │ ├── index.browser.ts │ │ │ ├── index.ts │ │ │ ├── toVirtualFile.test.ts │ │ │ └── toVirtualFile.ts │ ├── tsconfig.build.json │ ├── tsconfig.json │ └── wdio.config.ts └── snaps-webpack-plugin │ ├── .eslintrc.js │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── src │ ├── __snapshots__ │ │ └── plugin.test.ts.snap │ ├── index.ts │ ├── plugin.test.ts │ └── plugin.ts │ ├── tsconfig.build.json │ └── tsconfig.json ├── scripts ├── generate-preview-build-message.ts ├── get-release-tag.ts ├── get.sh ├── install-chrome.sh ├── prepare-preview-manifest.sh └── verify-tsconfig.mjs ├── tsconfig.build.json ├── tsconfig.json ├── tsconfig.packages.build.json ├── tsconfig.packages.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | 3 | yarn.lock linguist-generated=false 4 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Lines starting with '#' are comments. 2 | # Each line is a file pattern followed by one or more owners. 3 | 4 | * @MetaMask/snaps-devs 5 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Please see the documentation for all configuration options: 2 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 3 | 4 | version: 2 5 | updates: 6 | - package-ecosystem: 'npm' 7 | directory: '/' 8 | schedule: 9 | interval: 'daily' 10 | time: '06:00' 11 | allow: 12 | - dependency-name: '@metamask/*' 13 | target-branch: 'main' 14 | versioning-strategy: 'increase-if-necessary' 15 | open-pull-requests-limit: 10 16 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v18 2 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | // All of these are defaults except singleQuote, but we specify them 2 | // for explicitness 3 | module.exports = { 4 | quoteProps: 'as-needed', 5 | singleQuote: true, 6 | tabWidth: 2, 7 | trailingComma: 'all', 8 | }; 9 | -------------------------------------------------------------------------------- /.swcrc.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/swcrc", 3 | "jsc": { 4 | "parser": { 5 | "syntax": "typescript" 6 | }, 7 | "target": "es2020" 8 | }, 9 | "module": { 10 | "type": "commonjs" 11 | }, 12 | "exclude": [ 13 | ".*__fixtures__.*", 14 | ".*__mocks__.*", 15 | ".*__snapshots__.*", 16 | ".*__tests?__.*", 17 | ".*test-utils.*", 18 | ".*\\.test\\.?.*\\.tsx?", 19 | ".*\\.d\\.tsx?", 20 | ".*eval-worker\\.js" 21 | ], 22 | "sourceMaps": true 23 | } 24 | -------------------------------------------------------------------------------- /.yarn/patches/@babel-core-npm-7.21.0-fb3817b0e5.patch: -------------------------------------------------------------------------------- 1 | diff --git a/lib/index.js b/lib/index.js 2 | index 8b6dc73d1a71fb868cdd70c2ea98e543510ce80f..d32206166a2a9e33c20f1440876fe2dac2ad936a 100644 3 | --- a/lib/index.js 4 | +++ b/lib/index.js 5 | @@ -231,7 +231,6 @@ function _module() { 6 | }; 7 | return data; 8 | } 9 | -var thisFile = require("./index"); 10 | const version = "7.21.0"; 11 | exports.version = version; 12 | const DEFAULT_EXTENSIONS = Object.freeze([".js", ".jsx", ".es6", ".es", ".mjs", ".cjs"]); 13 | -------------------------------------------------------------------------------- /.yarn/patches/inline-source-map-npm-0.6.2-96902459a0.patch: -------------------------------------------------------------------------------- 1 | diff --git a/index.js b/index.js 2 | index df74d6126073947a34234f271a033c4d13ed02e5..833a4846989673c597500be60301a52132ebaa09 100644 3 | --- a/index.js 4 | +++ b/index.js 5 | @@ -91,7 +91,7 @@ Generator.prototype.addSourceContent = function (sourceFile, sourcesContent) { 6 | */ 7 | Generator.prototype.base64Encode = function () { 8 | var map = this.toString(); 9 | - return new Buffer(map).toString('base64'); 10 | + return Buffer.from(map).toString('base64'); 11 | }; 12 | 13 | /** 14 | -------------------------------------------------------------------------------- /.yarn/patches/jest-fetch-mock-npm-3.0.3-ac072ca8af.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/index.js b/src/index.js 2 | index 42015c1815447aab80df4524d1af91ac33e5751d..003aa9a2f0ce3ac4a65053b0b29ca0fe9b5c7ff3 100644 3 | --- a/src/index.js 4 | +++ b/src/index.js 5 | @@ -82,7 +82,8 @@ const isFn = unknown => typeof unknown === 'function' 6 | const isMocking = jest.fn(staticMatches(true)) 7 | 8 | const abortError = () => 9 | - new DOMException('The operation was aborted. ', 'AbortError') 10 | + // `DOMException` is not available in Node.js. 11 | + new Error('The operation was aborted. ') 12 | 13 | const abort = () => { 14 | throw abortError() 15 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | enableScripts: false 2 | 3 | enableTelemetry: 0 4 | 5 | logFilters: 6 | - code: YN0004 7 | level: discard 8 | 9 | nodeLinker: node-modules 10 | 11 | plugins: 12 | - path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs 13 | spec: '@yarnpkg/plugin-workspace-tools' 14 | - path: .yarn/plugins/@yarnpkg/plugin-allow-scripts.cjs 15 | spec: 'https://raw.githubusercontent.com/LavaMoat/LavaMoat/main/packages/yarn-plugin-allow-scripts/bundles/@yarnpkg/plugin-allow-scripts.js' 16 | - path: .yarn/plugins/@yarnpkg/plugin-constraints.cjs 17 | spec: '@yarnpkg/plugin-constraints' 18 | - path: .yarn/plugins/local/plugin-workspaces-filter.js 19 | 20 | yarnPath: .yarn/releases/yarn-3.4.1.cjs 21 | 22 | packageExtensions: 23 | '@wdio/browser-runner@*': 24 | dependencies: 25 | '@babel/core': '*' 26 | -------------------------------------------------------------------------------- /packages/create-snap/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | 8 | overrides: [ 9 | { 10 | files: ['**/*.ts'], 11 | extends: ['@metamask/eslint-config-nodejs'], 12 | globals: { 13 | snaps: true, 14 | }, 15 | }, 16 | 17 | { 18 | files: ['src/**/*', 'scripts/**/*'], 19 | rules: { 20 | 'node/no-process-exit': 'off', 21 | }, 22 | }, 23 | 24 | { 25 | files: ['src/main.ts'], 26 | rules: { 27 | 'node/shebang': 'off', 28 | }, 29 | }, 30 | 31 | { 32 | files: ['**/*.test.ts'], 33 | rules: { 34 | 'node/no-callback-literal': 'off', 35 | }, 36 | }, 37 | ], 38 | }; 39 | -------------------------------------------------------------------------------- /packages/create-snap/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2023 MetaMask 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /packages/create-snap/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | coveragePathIgnorePatterns: ['./src/types'], 7 | coverageThreshold: { 8 | global: { 9 | branches: 100, 10 | functions: 100, 11 | lines: 100, 12 | statements: 100, 13 | }, 14 | }, 15 | setupFiles: ['./test/setup.js'], 16 | }); 17 | -------------------------------------------------------------------------------- /packages/create-snap/src/__mocks__/fs.ts: -------------------------------------------------------------------------------- 1 | import { Volume } from 'memfs'; 2 | 3 | // Note: `Volume` implements most of the `fs` API, but not all. 4 | export = new Volume(); 5 | -------------------------------------------------------------------------------- /packages/create-snap/src/builders.ts: -------------------------------------------------------------------------------- 1 | import { Options, PositionalOptions } from 'yargs'; 2 | 3 | export type SnapsCliBuilders = { 4 | readonly verboseErrors: Readonly; 5 | readonly directory: Readonly; 6 | }; 7 | 8 | const builders: SnapsCliBuilders = { 9 | verboseErrors: { 10 | type: 'boolean', 11 | describe: 'Display original errors', 12 | demandOption: false, 13 | default: true, 14 | }, 15 | 16 | directory: { 17 | describe: 'The directory to use', 18 | type: 'string', 19 | }, 20 | }; 21 | 22 | export default builders; 23 | -------------------------------------------------------------------------------- /packages/create-snap/src/cmds/index.ts: -------------------------------------------------------------------------------- 1 | export { initCommand as init } from './init'; 2 | -------------------------------------------------------------------------------- /packages/create-snap/src/main.test.ts: -------------------------------------------------------------------------------- 1 | import * as cliModule from './cli'; 2 | 3 | jest.mock('./cli', () => ({ 4 | cli: jest.fn(), 5 | })); 6 | 7 | describe('main', () => { 8 | it('executes the CLI application', async () => { 9 | await import('./main'); 10 | expect(cliModule.cli).toHaveBeenCalledTimes(1); 11 | expect(cliModule.cli).toHaveBeenCalledWith(process.argv); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/create-snap/src/main.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { cli } from './cli'; 4 | 5 | cli(process.argv); 6 | -------------------------------------------------------------------------------- /packages/create-snap/src/test-utils/fs.ts: -------------------------------------------------------------------------------- 1 | import { promises as fs } from 'fs'; 2 | 3 | jest.mock('fs'); 4 | 5 | /** 6 | * Clears out all the files in the in-memory file system, and writes the default 7 | * folders to mimic the on-disk current working directory, including sub-folders. 8 | */ 9 | export async function resetFileSystem() { 10 | await fs.rm(process.cwd(), { recursive: true, force: true }); 11 | 12 | // Using relative path with memfs won't work since process.cwd() specifies the cwd of the on-disk file system 13 | // This recursively creates the current working directory in the memfs volume. 14 | // Ref. https://github.com/streamich/memfs/blob/master/docs/relative-paths.md 15 | await fs.mkdir(process.cwd(), { recursive: true }); 16 | } 17 | -------------------------------------------------------------------------------- /packages/create-snap/src/test-utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './fs'; 2 | -------------------------------------------------------------------------------- /packages/create-snap/src/types/snaps-cli.d.ts: -------------------------------------------------------------------------------- 1 | // We can't do "declare global" in this file without this, or else we get the 2 | // TS2669 error. 3 | // Kudos to: https://stackoverflow.com/a/59499895 4 | export {}; 5 | 6 | type SnapsCliGlobals = { 7 | verboseErrors?: boolean; 8 | suppressWarnings?: boolean; 9 | isWatching?: boolean; 10 | }; 11 | 12 | declare global { 13 | // eslint-disable-next-line no-var 14 | var snaps: SnapsCliGlobals; 15 | } 16 | -------------------------------------------------------------------------------- /packages/create-snap/src/types/yargs.d.ts: -------------------------------------------------------------------------------- 1 | import { Options } from 'yargs'; 2 | 3 | // eslint-disable-next-line @typescript-eslint/ban-types 4 | type OptionalArguments = T & { 5 | /** Non-option arguments */ 6 | _?: (string | number)[]; 7 | 8 | /** The script name or node command */ 9 | $0?: string; 10 | 11 | /** All remaining options */ 12 | [argName: string]: unknown; 13 | }; 14 | 15 | type YargsArgs = { 16 | directory?: string; 17 | } & OptionalArguments; 18 | 19 | type Option = { 20 | stripComments: boolean; 21 | transformHtmlComments: boolean; 22 | } & Options; 23 | -------------------------------------------------------------------------------- /packages/create-snap/test/setup.js: -------------------------------------------------------------------------------- 1 | global.snaps = { 2 | verboseErrors: false, 3 | }; 4 | -------------------------------------------------------------------------------- /packages/create-snap/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.build.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/types", 6 | "rootDir": "./src" 7 | }, 8 | "include": ["./src"], 9 | "exclude": [ 10 | "**/*.test.ts", 11 | "./src/**/test-utils", 12 | "./src/**/__mocks__", 13 | "./src/**/__snapshots__" 14 | ], 15 | "references": [ 16 | { "path": "../snaps-cli/tsconfig.build.json" }, 17 | { "path": "../snaps-utils/tsconfig.build.json" } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /packages/create-snap/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.json", 3 | "compilerOptions": { 4 | "baseUrl": "./" 5 | }, 6 | "include": ["./src", "./src/**/*.json"], 7 | "references": [{ "path": "../snaps-cli" }, { "path": "../snaps-utils" }] 8 | } 9 | -------------------------------------------------------------------------------- /packages/examples/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | 8 | ignorePatterns: [ 9 | '!.prettierrc.js', 10 | '**/!.eslintrc.js', 11 | '**/dist*/', 12 | 'packages/**', 13 | ], 14 | }; 15 | -------------------------------------------------------------------------------- /packages/examples/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/bip32/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/bip32/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/bip32/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | preset: '@metamask/snaps-jest', 7 | 8 | // Since `@metamask/snaps-jest` runs in the browser, we can't collect 9 | // coverage information. 10 | collectCoverage: false, 11 | 12 | // This is required for the tests to run inside the `MetaMask/snaps` 13 | // repository. You don't need this in your own project. 14 | moduleNameMapper: { 15 | '^@metamask/(.+)$': [ 16 | '/../../../$1/src', 17 | '/../../../../node_modules/@metamask/$1', 18 | '/node_modules/@metamask/$1', 19 | ], 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /packages/examples/packages/bip32/snap.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cliOptions: { 3 | port: 8001, 4 | src: './src/index.ts', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/examples/packages/bip32/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../*/src"] 7 | } 8 | }, 9 | "include": ["src"], 10 | "references": [ 11 | { 12 | "path": "../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../snaps-ui" 16 | }, 17 | { 18 | "path": "../../../snaps-jest" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/examples/packages/bip44/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/bip44/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/bip44/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | preset: '@metamask/snaps-jest', 7 | 8 | // Since `@metamask/snaps-jest` runs in the browser, we can't collect 9 | // coverage information. 10 | collectCoverage: false, 11 | 12 | // This is required for the tests to run inside the `MetaMask/snaps` 13 | // repository. You don't need this in your own project. 14 | moduleNameMapper: { 15 | '^@metamask/(.+)$': [ 16 | '/../../../$1/src', 17 | '/../../../../node_modules/@metamask/$1', 18 | '/node_modules/@metamask/$1', 19 | ], 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /packages/examples/packages/bip44/snap.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cliOptions: { 3 | port: 8002, 4 | src: './src/index.ts', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/examples/packages/bip44/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../*/src"] 7 | } 8 | }, 9 | "include": ["src"], 10 | "references": [ 11 | { 12 | "path": "../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../snaps-ui" 16 | }, 17 | { 18 | "path": "../../../snaps-jest" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/examples/packages/browserify-plugin/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/browserify-plugin/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/browserify-plugin/README.md: -------------------------------------------------------------------------------- 1 | # `@metamask/browserify-plugin-example-snap` 2 | 3 | This snap demonstrates how to use Browserify and the 4 | `@metamask/snaps-browserify-plugin` to bundle a snap. The MetaMask Snap CLI uses 5 | Browserify to bundle snaps by default, but if you need more control over the 6 | bundling process, you can use the `@metamask/snaps-browserify-plugin` to 7 | customize it. 8 | 9 | The snap is built in the [`scripts/build.ts`](./scripts/build.ts) script, which 10 | creates a Browserify instance and adds the `@metamask/snaps-browserify-plugin` 11 | to it. 12 | -------------------------------------------------------------------------------- /packages/examples/packages/browserify-plugin/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "chrome": "90" 8 | } 9 | } 10 | ], 11 | "@babel/preset-typescript" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /packages/examples/packages/browserify-plugin/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | preset: '@metamask/snaps-jest', 7 | 8 | // Since `@metamask/snaps-jest` runs in the browser, we can't collect 9 | // coverage information. 10 | collectCoverage: false, 11 | 12 | // This is required for the tests to run inside the `MetaMask/snaps` 13 | // repository. You don't need this in your own project. 14 | moduleNameMapper: { 15 | '^@metamask/(.+)$': [ 16 | '/../../../$1/src', 17 | '/../../../../node_modules/@metamask/$1', 18 | '/node_modules/@metamask/$1', 19 | ], 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /packages/examples/packages/browserify-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "resolveJsonModule": true, 5 | "baseUrl": "./", 6 | "paths": { 7 | "@metamask/*": ["../../../*/src"] 8 | } 9 | }, 10 | "include": ["src", "scripts", "babel.config.json"], 11 | "references": [ 12 | { 13 | "path": "../../../snaps-types" 14 | }, 15 | { 16 | "path": "../../../snaps-browserify-plugin" 17 | }, 18 | { 19 | "path": "../../../snaps-jest" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /packages/examples/packages/cronjobs/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/cronjobs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/cronjobs/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | preset: '@metamask/snaps-jest', 7 | 8 | // Since `@metamask/snaps-jest` runs in the browser, we can't collect 9 | // coverage information. 10 | collectCoverage: false, 11 | 12 | // This is required for the tests to run inside the `MetaMask/snaps` 13 | // repository. You don't need this in your own project. 14 | moduleNameMapper: { 15 | '^@metamask/(.+)$': [ 16 | '/../../../$1/src', 17 | '/../../../../node_modules/@metamask/$1', 18 | '/node_modules/@metamask/$1', 19 | ], 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /packages/examples/packages/cronjobs/snap.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cliOptions: { 3 | port: 8004, 4 | src: './src/index.ts', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/examples/packages/cronjobs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../*/src"] 7 | } 8 | }, 9 | "include": ["src"], 10 | "references": [ 11 | { 12 | "path": "../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../snaps-ui" 16 | }, 17 | { 18 | "path": "../../../snaps-jest" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/examples/packages/dialogs/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/dialogs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/dialogs/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | preset: '@metamask/snaps-jest', 7 | 8 | // Since `@metamask/snaps-jest` runs in the browser, we can't collect 9 | // coverage information. 10 | collectCoverage: false, 11 | 12 | // This is required for the tests to run inside the `MetaMask/snaps` 13 | // repository. You don't need this in your own project. 14 | moduleNameMapper: { 15 | '^@metamask/(.+)$': [ 16 | '/../../../$1/src', 17 | '/../../../../node_modules/@metamask/$1', 18 | '/node_modules/@metamask/$1', 19 | ], 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /packages/examples/packages/dialogs/snap.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cliOptions: { 3 | port: 8005, 4 | src: './src/index.ts', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/examples/packages/dialogs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../*/src"] 7 | } 8 | }, 9 | "include": ["src"], 10 | "references": [ 11 | { 12 | "path": "../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../snaps-ui" 16 | }, 17 | { 18 | "path": "../../../snaps-jest" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/examples/packages/errors/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/errors/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/errors/README.md: -------------------------------------------------------------------------------- 1 | # `@metamask/error-example-snap` 2 | 3 | This snap demonstrates how the Snaps platform handles out-of-band errors. 4 | 5 | > **Note**: This snap is primarily used for automated testing. It does not 6 | > provide any functionality to the user. 7 | 8 | ## Snap usage 9 | 10 | This snap exposes an `onRpcRequest` handler. It does not support any particular 11 | JSON-RPC methods, but simply returns a message. 12 | 13 | For more information, you can refer to 14 | [the end-to-end tests](./src/index.test.ts). 15 | -------------------------------------------------------------------------------- /packages/examples/packages/errors/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | preset: '@metamask/snaps-jest', 7 | 8 | // Since `@metamask/snaps-jest` runs in the browser, we can't collect 9 | // coverage information. 10 | collectCoverage: false, 11 | 12 | // This is required for the tests to run inside the `MetaMask/snaps` 13 | // repository. You don't need this in your own project. 14 | moduleNameMapper: { 15 | '^@metamask/(.+)$': [ 16 | '/../../../$1/src', 17 | '/../../../../node_modules/@metamask/$1', 18 | '/node_modules/@metamask/$1', 19 | ], 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /packages/examples/packages/errors/snap.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cliOptions: { 3 | port: 8006, 4 | src: './src/index.ts', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/examples/packages/errors/snap.manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.34.1-flask.1", 3 | "description": "MetaMask example snap demonstrating the use of error handling in snaps.", 4 | "proposedName": "Error Example Snap", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/MetaMask/snaps.git" 8 | }, 9 | "source": { 10 | "shasum": "h1pTRKsFDfrOk8eXyoUH/deXgtiMQwvxLwY+W8H0H0M=", 11 | "location": { 12 | "npm": { 13 | "filePath": "dist/bundle.js", 14 | "iconPath": "images/icon.svg", 15 | "packageName": "@metamask/error-example-snap", 16 | "registry": "https://registry.npmjs.org/" 17 | } 18 | } 19 | }, 20 | "initialPermissions": { 21 | "endowment:rpc": { 22 | "dapps": true 23 | } 24 | }, 25 | "manifestVersion": "0.1" 26 | } 27 | -------------------------------------------------------------------------------- /packages/examples/packages/errors/src/index.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from '@jest/globals'; 2 | import { installSnap } from '@metamask/snaps-jest'; 3 | 4 | describe('onRpcRequest', () => { 5 | it('returns "Hello, world!" and does not throw an error', async () => { 6 | const { request, close } = await installSnap(); 7 | 8 | const response = request({ 9 | method: 'foo', 10 | }); 11 | 12 | expect(await response).toRespondWith('Hello, world!'); 13 | 14 | await close(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/examples/packages/errors/src/index.ts: -------------------------------------------------------------------------------- 1 | import { OnRpcRequestHandler } from '@metamask/snaps-types'; 2 | 3 | export const onRpcRequest: OnRpcRequestHandler = async () => { 4 | // eslint-disable-next-line no-new, @typescript-eslint/no-floating-promises 5 | new Promise(() => { 6 | let value = 0; 7 | while (value < 100) { 8 | // eslint-disable-next-line no-plusplus 9 | value++; 10 | } 11 | 12 | throw new Error('Random error inside a promise.'); 13 | }); 14 | 15 | return 'Hello, world!'; 16 | }; 17 | -------------------------------------------------------------------------------- /packages/examples/packages/errors/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../*/src"] 7 | } 8 | }, 9 | "include": ["src"], 10 | "references": [ 11 | { 12 | "path": "../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../snaps-ui" 16 | }, 17 | { 18 | "path": "../../../snaps-jest" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/examples/packages/ethereum-provider/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/ethereum-provider/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/ethereum-provider/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | preset: '@metamask/snaps-jest', 7 | 8 | // Since `@metamask/snaps-jest` runs in the browser, we can't collect 9 | // coverage information. 10 | collectCoverage: false, 11 | 12 | // This is required for the tests to run inside the `MetaMask/snaps` 13 | // repository. You don't need this in your own project. 14 | moduleNameMapper: { 15 | '^@metamask/(.+)$': [ 16 | '/../../../$1/src', 17 | '/../../../../node_modules/@metamask/$1', 18 | '/node_modules/@metamask/$1', 19 | ], 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /packages/examples/packages/ethereum-provider/snap.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cliOptions: { 3 | port: 8007, 4 | src: './src/index.ts', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/examples/packages/ethereum-provider/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../*/src"] 7 | } 8 | }, 9 | "include": ["src"], 10 | "references": [ 11 | { 12 | "path": "../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../snaps-ui" 16 | }, 17 | { 18 | "path": "../../../snaps-jest" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/examples/packages/ethers-js/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/ethers-js/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/ethers-js/snap.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cliOptions: { 3 | port: 8008, 4 | src: './src/index.ts', 5 | transpilationMode: 'localAndDeps', 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/ethers-js/src/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The parameters for the `signMessage` JSON-RPC method. 3 | */ 4 | export type SignMessageParams = { 5 | /** 6 | * The message to sign. It will be signed using the snap's signing key, 7 | * derived with the [`snap_getEntropy`](https://docs.metamask.io/snaps/reference/rpc-api/#snap_getentropy) 8 | * method. 9 | */ 10 | message: string; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/examples/packages/ethers-js/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../*/src"] 7 | } 8 | }, 9 | "include": ["src"], 10 | "references": [ 11 | { 12 | "path": "../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../snaps-ui" 16 | }, 17 | { 18 | "path": "../../../snaps-jest" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/examples/packages/get-entropy/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/get-entropy/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/get-entropy/snap.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cliOptions: { 3 | port: 8009, 4 | src: './src/index.ts', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/examples/packages/get-entropy/src/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The parameters for the `signMessage` JSON-RPC method. 3 | */ 4 | export type SignMessageParams = { 5 | /** 6 | * The message to sign. 7 | */ 8 | message: string; 9 | 10 | /** 11 | * The salt to use for the entropy derivation. Using a different salt will 12 | * result in completely different entropy being generated, and thus a 13 | * completely different signature. 14 | * 15 | * Defaults to "Signing key". 16 | */ 17 | salt?: string; 18 | }; 19 | -------------------------------------------------------------------------------- /packages/examples/packages/get-entropy/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../*/src"] 7 | } 8 | }, 9 | "include": ["src"], 10 | "references": [ 11 | { 12 | "path": "../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../snaps-ui" 16 | }, 17 | { 18 | "path": "../../../snaps-jest" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/examples/packages/invoke-snap/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | 8 | ignorePatterns: [ 9 | '!.prettierrc.js', 10 | '**/!.eslintrc.js', 11 | '**/dist*/', 12 | 'packages/**', 13 | ], 14 | }; 15 | -------------------------------------------------------------------------------- /packages/examples/packages/invoke-snap/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/invoke-snap/packages/consumer-signer/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/invoke-snap/packages/consumer-signer/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/invoke-snap/packages/consumer-signer/README.md: -------------------------------------------------------------------------------- 1 | # `@metamask/consumer-signer-example-snap` 2 | 3 | This snap demonstrates how to use the `wallet_invokeSnap` method to invoke 4 | another snap. In this case, we invoke the core signer snap to sign a message 5 | using a private key derived from generated entropy. 6 | 7 | For simplicity, the snap does not actually sign Ethereum-compatible messages. It 8 | uses Ethereum's BIP-44 derivation path, to demonstrate how to use the 9 | `wallet_invokeSnap` method to use another snap's functionality. 10 | 11 | ## Snap usage 12 | 13 | This snap exposes an `onRpcRequest` handler, which supports the following 14 | JSON-RPC methods: 15 | 16 | - `signMessage`: Get an account from the core signer snap, and sign a message 17 | using the account's private key. 18 | -------------------------------------------------------------------------------- /packages/examples/packages/invoke-snap/packages/consumer-signer/snap.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cliOptions: { 3 | port: 8012, 4 | src: './src/index.ts', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/examples/packages/invoke-snap/packages/consumer-signer/src/types.ts: -------------------------------------------------------------------------------- 1 | import { PartialHDPathTuple5 } from '@metamask/key-tree'; 2 | 3 | /** 4 | * A BIP-44 path is of the form: 5 | * 6 | * `m / 44' / coin_type' / account' / change / address_index` 7 | * 8 | * This type represents the last 5 elements of the path in the form of a tuple. 9 | */ 10 | export type BIP44Path = PartialHDPathTuple5; 11 | 12 | /** 13 | * The parameters for the `signMessage` JSON-RPC method. 14 | */ 15 | export type SignMessageParams = { 16 | /** 17 | * The message to sign. 18 | */ 19 | message: string; 20 | 21 | /** 22 | * The derivation path to derive the account from. If not provided, the 23 | * default derivation path for Ethereum is used. 24 | */ 25 | path?: BIP44Path; 26 | }; 27 | -------------------------------------------------------------------------------- /packages/examples/packages/invoke-snap/packages/consumer-signer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../../../*/src"] 7 | } 8 | }, 9 | "include": ["src"], 10 | "references": [ 11 | { 12 | "path": "../../../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../../../snaps-jest" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /packages/examples/packages/invoke-snap/packages/core-signer/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/invoke-snap/packages/core-signer/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/invoke-snap/packages/core-signer/snap.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cliOptions: { 3 | port: 8011, 4 | src: './src/index.ts', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/examples/packages/invoke-snap/packages/core-signer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../../../*/src"] 7 | } 8 | }, 9 | "include": ["src"], 10 | "references": [ 11 | { 12 | "path": "../../../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../../../snaps-ui" 16 | }, 17 | { 18 | "path": "../../../../../snaps-jest" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/examples/packages/invoke-snap/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../*/src"] 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/examples/packages/json-rpc/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/json-rpc/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/json-rpc/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | preset: '@metamask/snaps-jest', 7 | 8 | // Since `@metamask/snaps-jest` runs in the browser, we can't collect 9 | // coverage information. 10 | collectCoverage: false, 11 | 12 | // This is required for the tests to run inside the `MetaMask/snaps` 13 | // repository. You don't need this in your own project. 14 | moduleNameMapper: { 15 | '^@metamask/(.+)$': [ 16 | '/../../../$1/src', 17 | '/../../../../node_modules/@metamask/$1', 18 | '/node_modules/@metamask/$1', 19 | ], 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /packages/examples/packages/json-rpc/snap.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cliOptions: { 3 | port: 8013, 4 | src: './src/index.ts', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/examples/packages/json-rpc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../*/src"] 7 | } 8 | }, 9 | "include": ["src"], 10 | "references": [ 11 | { 12 | "path": "../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../snaps-jest" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /packages/examples/packages/manage-state/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/manage-state/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/manage-state/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | preset: '@metamask/snaps-jest', 7 | 8 | // Since `@metamask/snaps-jest` runs in the browser, we can't collect 9 | // coverage information. 10 | collectCoverage: false, 11 | 12 | // This is required for the tests to run inside the `MetaMask/snaps` 13 | // repository. You don't need this in your own project. 14 | moduleNameMapper: { 15 | '^@metamask/(.+)$': [ 16 | '/../../../$1/src', 17 | '/../../../../node_modules/@metamask/$1', 18 | '/node_modules/@metamask/$1', 19 | ], 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /packages/examples/packages/manage-state/snap.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cliOptions: { 3 | port: 8014, 4 | src: './src/index.ts', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/examples/packages/manage-state/src/types.ts: -------------------------------------------------------------------------------- 1 | import { State } from './utils'; 2 | 3 | /** 4 | * The parameters for the `setState` JSON-RPC method. 5 | * 6 | * The current state will be merged with the new state. 7 | */ 8 | export type SetStateParams = Partial; 9 | -------------------------------------------------------------------------------- /packages/examples/packages/manage-state/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../*/src"] 7 | } 8 | }, 9 | "include": ["src"], 10 | "references": [ 11 | { 12 | "path": "../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../snaps-jest" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /packages/examples/packages/network-access/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/network-access/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/network-access/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | preset: '@metamask/snaps-jest', 7 | 8 | // Since `@metamask/snaps-jest` runs in the browser, we can't collect 9 | // coverage information. 10 | collectCoverage: false, 11 | 12 | // This is required for the tests to run inside the `MetaMask/snaps` 13 | // repository. You don't need this in your own project. 14 | moduleNameMapper: { 15 | '^@metamask/(.+)$': [ 16 | '/../../../$1/src', 17 | '/../../../../node_modules/@metamask/$1', 18 | '/node_modules/@metamask/$1', 19 | ], 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /packages/examples/packages/network-access/snap.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cliOptions: { 3 | port: 8015, 4 | src: './src/index.ts', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/examples/packages/network-access/src/constants.ts: -------------------------------------------------------------------------------- 1 | import { version } from '../package.json'; 2 | 3 | export const DEFAULT_URL = `https://metamask.github.io/snaps/test-snaps/${version}/test-data.json`; 4 | -------------------------------------------------------------------------------- /packages/examples/packages/network-access/src/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The params for the `fetch` JSON-RPC method. 3 | */ 4 | export type FetchParams = { 5 | /** 6 | * The URL to fetch. Defaults to 7 | * `https://metamask.github.io/snaps/test-snaps/latest/test-data.json`. 8 | */ 9 | url?: string; 10 | }; 11 | -------------------------------------------------------------------------------- /packages/examples/packages/network-access/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../*/src"] 7 | } 8 | }, 9 | "include": ["src", "package.json"], 10 | "references": [ 11 | { 12 | "path": "../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../snaps-jest" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /packages/examples/packages/notifications/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/notifications/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/notifications/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | preset: '@metamask/snaps-jest', 7 | 8 | // Since `@metamask/snaps-jest` runs in the browser, we can't collect 9 | // coverage information. 10 | collectCoverage: false, 11 | 12 | // This is required for the tests to run inside the `MetaMask/snaps` 13 | // repository. You don't need this in your own project. 14 | moduleNameMapper: { 15 | '^@metamask/(.+)$': [ 16 | '/../../../$1/src', 17 | '/../../../../node_modules/@metamask/$1', 18 | '/node_modules/@metamask/$1', 19 | ], 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /packages/examples/packages/notifications/snap.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cliOptions: { 3 | port: 8016, 4 | src: './src/index.ts', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/examples/packages/notifications/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../*/src"] 7 | } 8 | }, 9 | "include": ["src"], 10 | "references": [ 11 | { 12 | "path": "../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../snaps-ui" 16 | }, 17 | { 18 | "path": "../../../snaps-jest" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/examples/packages/rollup-plugin/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | 8 | overrides: [ 9 | { 10 | files: ['rollup.config.js'], 11 | parserOptions: { 12 | sourceType: 'module', 13 | }, 14 | rules: { 15 | 'import/no-unresolved': 'off', 16 | }, 17 | }, 18 | ], 19 | }; 20 | -------------------------------------------------------------------------------- /packages/examples/packages/rollup-plugin/.gitignore: -------------------------------------------------------------------------------- 1 | .rollup.cache 2 | -------------------------------------------------------------------------------- /packages/examples/packages/rollup-plugin/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/rollup-plugin/README.md: -------------------------------------------------------------------------------- 1 | # `@metamask/rollup-plugin-example-snap` 2 | 3 | This snap demonstrates how to use Rollup and the 4 | [`@metamask/snaps-rollup-plugin`](../../../snaps-rollup-plugin) to bundle a 5 | snap. The MetaMask Snap CLI uses Browserify to bundle snaps by default, but 6 | if you prefer to use Rollup, you can use `@metamask/snaps-rollup-plugin` to do 7 | so. 8 | 9 | Rollup is configured in the [`rollup.config.js`](./rollup.config.js) file. It 10 | sets up Node.js resolution, CommonJS transpilation, and a few other things. 11 | -------------------------------------------------------------------------------- /packages/examples/packages/rollup-plugin/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "chrome": "90" 8 | } 9 | } 10 | ], 11 | "@babel/preset-typescript" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /packages/examples/packages/rollup-plugin/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | preset: '@metamask/snaps-jest', 7 | 8 | // Since `@metamask/snaps-jest` runs in the browser, we can't collect 9 | // coverage information. 10 | collectCoverage: false, 11 | 12 | // This is required for the tests to run inside the `MetaMask/snaps` 13 | // repository. You don't need this in your own project. 14 | moduleNameMapper: { 15 | '^@metamask/(.+)$': [ 16 | '/../../../$1/src', 17 | '/../../../../node_modules/@metamask/$1', 18 | '/node_modules/@metamask/$1', 19 | ], 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /packages/examples/packages/rollup-plugin/snap.manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.34.1-flask.1", 3 | "description": "MetaMask example snap demonstrating how to use the Rollup plugin to bundle a snap.", 4 | "proposedName": "Rollup Plugin Example Snap", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/MetaMask/snaps.git" 8 | }, 9 | "source": { 10 | "shasum": "1RjPYC0YvL4jofwM7lSU9AbCuIC12l9cI3fl5y6bOnY=", 11 | "location": { 12 | "npm": { 13 | "filePath": "dist/bundle.js", 14 | "packageName": "@metamask/rollup-plugin-example-snap", 15 | "registry": "https://registry.npmjs.org" 16 | } 17 | } 18 | }, 19 | "initialPermissions": { 20 | "endowment:rpc": { 21 | "dapps": true 22 | } 23 | }, 24 | "manifestVersion": "0.1" 25 | } 26 | -------------------------------------------------------------------------------- /packages/examples/packages/rollup-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../*/src"] 7 | } 8 | }, 9 | "include": ["src", "rollup.config.js"], 10 | "references": [ 11 | { 12 | "path": "../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../snaps-rollup-plugin" 16 | }, 17 | { 18 | "path": "../../../snaps-jest" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/examples/packages/transaction-insights/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/transaction-insights/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/transaction-insights/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | preset: '@metamask/snaps-jest', 7 | 8 | // Since `@metamask/snaps-jest` runs in the browser, we can't collect 9 | // coverage information. 10 | collectCoverage: false, 11 | 12 | // This is required for the tests to run inside the `MetaMask/snaps` 13 | // repository. You don't need this in your own project. 14 | moduleNameMapper: { 15 | '^@metamask/(.+)$': [ 16 | '/../../../$1/src', 17 | '/../../../../node_modules/@metamask/$1', 18 | '/node_modules/@metamask/$1', 19 | ], 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /packages/examples/packages/transaction-insights/snap.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cliOptions: { 3 | port: 8018, 4 | src: './src/index.ts', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/examples/packages/transaction-insights/snap.manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.34.1-flask.1", 3 | "description": "MetaMask example snap demonstrating the use of the Transaction Insights API.", 4 | "proposedName": "Insights Example Snap", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/MetaMask/snaps.git" 8 | }, 9 | "source": { 10 | "shasum": "rnLEr07iZAjaXo2UJant9yaIwUXBiY54KQP06v307XE=", 11 | "location": { 12 | "npm": { 13 | "filePath": "dist/bundle.js", 14 | "packageName": "@metamask/insights-example-snap", 15 | "registry": "https://registry.npmjs.org/" 16 | } 17 | } 18 | }, 19 | "initialPermissions": { 20 | "endowment:transaction-insight": {} 21 | }, 22 | "manifestVersion": "0.1" 23 | } 24 | -------------------------------------------------------------------------------- /packages/examples/packages/transaction-insights/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../*/src"] 7 | } 8 | }, 9 | "include": ["src"], 10 | "references": [ 11 | { 12 | "path": "../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../snaps-ui" 16 | }, 17 | { 18 | "path": "../../../snaps-jest" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/examples/packages/wasm/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | 8 | ignorePatterns: [ 9 | '!.prettierrc.js', 10 | '**/!.eslintrc.js', 11 | '**/dist*/', 12 | 'packages/**', 13 | 'program/**', 14 | 'build/**', 15 | ], 16 | }; 17 | -------------------------------------------------------------------------------- /packages/examples/packages/wasm/.gitignore: -------------------------------------------------------------------------------- 1 | # WebAssembly build files 2 | build 3 | -------------------------------------------------------------------------------- /packages/examples/packages/wasm/.swcrc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/swcrc", 3 | "jsc": { 4 | "parser": { 5 | "syntax": "typescript" 6 | }, 7 | "target": "es2021" 8 | }, 9 | "module": { 10 | "type": "es6" 11 | }, 12 | "minify": false 13 | } 14 | 15 | -------------------------------------------------------------------------------- /packages/examples/packages/wasm/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/wasm/asconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "entries": ["./assembly/program.ts"], 3 | "targets": { 4 | "release": { 5 | "bindings": "raw", 6 | "converge": true, 7 | "optimize": true, 8 | "outFile": "./build/program.wasm" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/examples/packages/wasm/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | preset: '@metamask/snaps-jest', 7 | 8 | // Since `@metamask/snaps-jest` runs in the browser, we can't collect 9 | // coverage information. 10 | collectCoverage: false, 11 | 12 | // This is required for the tests to run inside the `MetaMask/snaps` 13 | // repository. You don't need this in your own project. 14 | moduleNameMapper: { 15 | '^@metamask/(.+)$': [ 16 | '/../../../$1/src', 17 | '/../../../../node_modules/@metamask/$1', 18 | '/node_modules/@metamask/$1', 19 | ], 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /packages/examples/packages/wasm/src/types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is used to declare types for assets that are not natively 3 | * supported by TypeScript. This works because we are using Webpack to bundle 4 | * these assets. 5 | * 6 | * For example, WebAssembly modules are not natively supported by TypeScript, 7 | * so we need to declare a type for them here. This allows us to import them 8 | * in our code, and have TypeScript understand that they are valid modules. 9 | */ 10 | // eslint-disable-next-line import/unambiguous 11 | declare module '*.wasm' { 12 | const module: string; 13 | export default module; 14 | } 15 | -------------------------------------------------------------------------------- /packages/examples/packages/wasm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../*/src"] 7 | } 8 | }, 9 | "include": ["src", "assembly", "webpack.config.ts"], 10 | "references": [ 11 | { 12 | "path": "../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../snaps-ui" 16 | }, 17 | { 18 | "path": "../../../snaps-webpack-plugin" 19 | }, 20 | { 21 | "path": "../../../snaps-jest" 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /packages/examples/packages/webpack-plugin/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/examples/packages/webpack-plugin/.swcrc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/swcrc", 3 | "jsc": { 4 | "parser": { 5 | "syntax": "typescript" 6 | }, 7 | "target": "es2021" 8 | }, 9 | "module": { 10 | "type": "es6" 11 | }, 12 | "minify": false 13 | } 14 | 15 | -------------------------------------------------------------------------------- /packages/examples/packages/webpack-plugin/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/examples/packages/webpack-plugin/README.md: -------------------------------------------------------------------------------- 1 | # `@metamask/webpack-plugin-example-snap` 2 | 3 | This snap demonstrates how to use Webpack and the 4 | [`@metamask/snaps-webpack-plugin`](../../../snaps-webpack-plugin) to bundle a 5 | snap. The MetaMask Snap CLI uses Browserify to bundle snaps by default, but 6 | if you prefer to use Webpack, you can use `@metamask/snaps-webpack-plugin` to do 7 | so. 8 | 9 | Webpack is configured in the [`webpack.config.ts`](./webpack.config.ts) file. It 10 | sets up a basic configuration that bundles the snap's source code into a single 11 | file, and outputs it to the `dist/` directory. 12 | -------------------------------------------------------------------------------- /packages/examples/packages/webpack-plugin/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | preset: '@metamask/snaps-jest', 7 | 8 | // Since `@metamask/snaps-jest` runs in the browser, we can't collect 9 | // coverage information. 10 | collectCoverage: false, 11 | 12 | // This is required for the tests to run inside the `MetaMask/snaps` 13 | // repository. You don't need this in your own project. 14 | moduleNameMapper: { 15 | '^@metamask/(.+)$': [ 16 | '/../../../$1/src', 17 | '/../../../../node_modules/@metamask/$1', 18 | '/node_modules/@metamask/$1', 19 | ], 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /packages/examples/packages/webpack-plugin/snap.manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.34.1-flask.1", 3 | "description": "MetaMask example snap demonstrating how to use the Webpack plugin to bundle a snap.", 4 | "proposedName": "Webpack Plugin Example Snap", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/MetaMask/snaps.git" 8 | }, 9 | "source": { 10 | "shasum": "7xS/7tCxiHfX5mqq/BoPql+viK1ncgNNfmlkygQU1Lw=", 11 | "location": { 12 | "npm": { 13 | "filePath": "dist/bundle.js", 14 | "packageName": "@metamask/webpack-plugin-example-snap", 15 | "registry": "https://registry.npmjs.org" 16 | } 17 | } 18 | }, 19 | "initialPermissions": { 20 | "endowment:rpc": { 21 | "dapps": true 22 | } 23 | }, 24 | "manifestVersion": "0.1" 25 | } 26 | -------------------------------------------------------------------------------- /packages/examples/packages/webpack-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@metamask/*": ["../../../*/src"] 7 | } 8 | }, 9 | "include": ["src", "webpack.config.ts"], 10 | "references": [ 11 | { 12 | "path": "../../../snaps-types" 13 | }, 14 | { 15 | "path": "../../../snaps-webpack-plugin" 16 | }, 17 | { 18 | "path": "../../../snaps-jest" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/examples/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.json", 3 | "compilerOptions": { 4 | "baseUrl": "./" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/rpc-methods/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | overrides: [ 5 | { 6 | files: ['**/*test.ts'], 7 | rules: { 8 | 'jest/expect-expect': [ 9 | 'error', 10 | { 11 | assertFunctionNames: ['expect', 'expectTypeOf'], 12 | }, 13 | ], 14 | }, 15 | }, 16 | ], 17 | 18 | parserOptions: { 19 | tsconfigRootDir: __dirname, 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /packages/rpc-methods/README.md: -------------------------------------------------------------------------------- 1 | # @metamask/rpc-methods 2 | 3 | JSON-RPC methods for MetaMask Snaps functionality. 4 | -------------------------------------------------------------------------------- /packages/rpc-methods/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | collectCoverageFrom: [ 7 | './src/**/*.ts', 8 | '!./src/**/*.test.ts', 9 | '!./src/**/index.ts', 10 | ], 11 | coverageThreshold: { 12 | global: { 13 | branches: 85.84, 14 | functions: 100, 15 | lines: 97.88, 16 | statements: 96.45, 17 | }, 18 | }, 19 | }); 20 | -------------------------------------------------------------------------------- /packages/rpc-methods/src/__fixtures__/index.ts: -------------------------------------------------------------------------------- 1 | export * from './entropy'; 2 | -------------------------------------------------------------------------------- /packages/rpc-methods/src/index.ts: -------------------------------------------------------------------------------- 1 | export type { PermittedRpcMethodHooks } from './permitted'; 2 | export { 3 | handlers as permittedMethods, 4 | createSnapsMethodMiddleware, 5 | } from './permitted'; 6 | export * from './restricted'; 7 | export { SnapCaveatType } from '@metamask/snaps-utils'; 8 | export { selectHooks } from './utils'; 9 | export type { RequestFunction, SnapsGlobalObject } from './request'; 10 | -------------------------------------------------------------------------------- /packages/rpc-methods/src/permitted/handlers.ts: -------------------------------------------------------------------------------- 1 | import { getSnapsHandler } from './getSnaps'; 2 | import { invokeSnapSugarHandler } from './invokeSnapSugar'; 3 | import { requestSnapsHandler } from './requestSnaps'; 4 | 5 | /* eslint-disable @typescript-eslint/naming-convention */ 6 | export const methodHandlers = { 7 | wallet_getSnaps: getSnapsHandler, 8 | wallet_requestSnaps: requestSnapsHandler, 9 | wallet_invokeSnap: invokeSnapSugarHandler, 10 | }; 11 | /* eslint-enable @typescript-eslint/naming-convention */ 12 | 13 | export const handlers = Object.values(methodHandlers); 14 | -------------------------------------------------------------------------------- /packages/rpc-methods/src/permitted/index.ts: -------------------------------------------------------------------------------- 1 | import { GetSnapsHooks } from './getSnaps'; 2 | import { RequestSnapsHooks } from './requestSnaps'; 3 | 4 | export type PermittedRpcMethodHooks = GetSnapsHooks & RequestSnapsHooks; 5 | 6 | export * from './handlers'; 7 | export * from './middleware'; 8 | -------------------------------------------------------------------------------- /packages/rpc-methods/src/utils.test.ts: -------------------------------------------------------------------------------- 1 | import { SIP_6_MAGIC_VALUE } from '@metamask/snaps-utils'; 2 | import { TEST_SECRET_RECOVERY_PHRASE_BYTES } from '@metamask/snaps-utils/test-utils'; 3 | 4 | import { ENTROPY_VECTORS } from './__fixtures__'; 5 | import { deriveEntropy } from './utils'; 6 | 7 | describe('deriveEntropy', () => { 8 | it.each(ENTROPY_VECTORS)( 9 | 'derives entropy from the given parameters', 10 | async ({ snapId, salt, entropy }) => { 11 | expect( 12 | await deriveEntropy({ 13 | input: snapId, 14 | salt, 15 | mnemonicPhrase: TEST_SECRET_RECOVERY_PHRASE_BYTES, 16 | magic: SIP_6_MAGIC_VALUE, 17 | }), 18 | ).toStrictEqual(entropy); 19 | }, 20 | ); 21 | }); 22 | -------------------------------------------------------------------------------- /packages/rpc-methods/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.build.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/types", 6 | "rootDir": "./src" 7 | }, 8 | "include": ["./src"], 9 | "exclude": [ 10 | "**/*.test.ts", 11 | "./src/**/test-utils", 12 | "./src/**/__mocks__", 13 | "./src/**/__snapshots__" 14 | ], 15 | "references": [ 16 | { 17 | "path": "../snaps-utils/tsconfig.build.json" 18 | }, 19 | { 20 | "path": "../snaps-ui/tsconfig.build.json" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/rpc-methods/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.json", 3 | "compilerOptions": { 4 | "baseUrl": "./" 5 | }, 6 | "include": ["./src"], 7 | "references": [{ "path": "../snaps-utils" }, { "path": "../snaps-ui" }] 8 | } 9 | -------------------------------------------------------------------------------- /packages/snaps-browserify-plugin/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/snaps-browserify-plugin/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | dist 4 | dist-temp 5 | temp 6 | *.log 7 | *.tgz 8 | 9 | public/ 10 | src/__GENERATED__/ 11 | -------------------------------------------------------------------------------- /packages/snaps-browserify-plugin/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2022 MetaMask 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /packages/snaps-browserify-plugin/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | coverageThreshold: { 7 | global: { 8 | branches: 100, 9 | functions: 100, 10 | lines: 100, 11 | statements: 100, 12 | }, 13 | }, 14 | }); 15 | -------------------------------------------------------------------------------- /packages/snaps-browserify-plugin/src/__mocks__/fs.ts: -------------------------------------------------------------------------------- 1 | import { Volume } from 'memfs'; 2 | 3 | // Note: `Volume` implements most of the `fs` API, but not all. 4 | const volume = new Volume(); 5 | 6 | // Part of the real `fs` API is used here, since Browserify uses it to load 7 | // certain modules from the file system. The async methods are not used, so 8 | // they are mocked. 9 | export = { ...jest.requireActual('fs'), promises: volume.promises }; 10 | -------------------------------------------------------------------------------- /packages/snaps-browserify-plugin/src/index.ts: -------------------------------------------------------------------------------- 1 | import plugin from './plugin'; 2 | 3 | export { default } from './plugin'; 4 | export type { Options } from './plugin'; 5 | 6 | // This is required for Browserify to work when specifying just the module name, 7 | // rather than importing the plugin function. 8 | module.exports = plugin; 9 | -------------------------------------------------------------------------------- /packages/snaps-browserify-plugin/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.build.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/types", 6 | "rootDir": "./src" 7 | }, 8 | "include": ["./src"], 9 | "exclude": [ 10 | "**/*.test.ts", 11 | "./src/**/test-utils", 12 | "./src/**/__mocks__", 13 | "./src/**/__snapshots__" 14 | ], 15 | "references": [ 16 | { 17 | "path": "../snaps-utils/tsconfig.build.json" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/snaps-browserify-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.json", 3 | "compilerOptions": { 4 | "baseUrl": "./" 5 | }, 6 | "include": ["./src"], 7 | "references": [ 8 | { 9 | "path": "../snaps-utils" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /packages/snaps-cli/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2021 MetaMask 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /packages/snaps-cli/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /packages/snaps-cli/src/__mocks__/fs.ts: -------------------------------------------------------------------------------- 1 | import { Volume } from 'memfs'; 2 | 3 | // Note: `Volume` implements most of the `fs` API, but not all. 4 | export = new Volume(); 5 | -------------------------------------------------------------------------------- /packages/snaps-cli/src/cmds/eval/__test__/eval-2.js: -------------------------------------------------------------------------------- 1 | // This file is used for the E2E eval test. 2 | 3 | throw new Error('Eval failed.'); 4 | -------------------------------------------------------------------------------- /packages/snaps-cli/src/cmds/eval/index.test.ts: -------------------------------------------------------------------------------- 1 | import index from '.'; 2 | import { YargsArgs } from '../../types/yargs'; 3 | import { evalHandler } from './evalHandler'; 4 | 5 | jest.mock('./evalHandler'); 6 | 7 | const getMockArgv = ({ bundle = 'dist/snap.js' } = {}) => { 8 | return { bundle } as unknown as YargsArgs; 9 | }; 10 | 11 | const evalHandlerMock = evalHandler as jest.MockedFunction; 12 | 13 | describe('handler', () => { 14 | it('calls evalHandler', async () => { 15 | await index.handler(getMockArgv()); 16 | 17 | expect(evalHandlerMock).toHaveBeenCalled(); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /packages/snaps-cli/src/cmds/eval/index.ts: -------------------------------------------------------------------------------- 1 | import yargs from 'yargs'; 2 | 3 | import builders from '../../builders'; 4 | import { YargsArgs } from '../../types/yargs'; 5 | import { evalHandler } from './evalHandler'; 6 | 7 | const command = { 8 | command: ['eval', 'e'], 9 | desc: 'Attempt to evaluate Snap bundle in SES', 10 | builder: (yarg: yargs.Argv) => { 11 | yarg.option('bundle', builders.bundle); 12 | }, 13 | handler: async (argv: YargsArgs) => evalHandler(argv), 14 | }; 15 | 16 | export default command; 17 | -------------------------------------------------------------------------------- /packages/snaps-cli/src/cmds/index.ts: -------------------------------------------------------------------------------- 1 | import build from './build'; 2 | import evaluate from './eval'; 3 | import manifest from './manifest'; 4 | import serve from './serve'; 5 | import watch from './watch'; 6 | 7 | const commands = [build, evaluate, manifest, serve, watch]; 8 | export default commands; 9 | -------------------------------------------------------------------------------- /packages/snaps-cli/src/cmds/manifest/index.ts: -------------------------------------------------------------------------------- 1 | import yargs from 'yargs'; 2 | 3 | import builders from '../../builders'; 4 | import { YargsArgs } from '../../types/yargs'; 5 | import { logError } from '../../utils'; 6 | import { manifestHandler } from './manifestHandler'; 7 | 8 | const command = { 9 | command: ['manifest', 'm'], 10 | desc: 'Validate the snap.manifest.json file', 11 | builder: (yarg: yargs.Argv) => { 12 | yarg.option('writeManifest', { ...builders.writeManifest, alias: ['fix'] }); 13 | }, 14 | handler: async (argv: YargsArgs) => { 15 | try { 16 | await manifestHandler(argv); 17 | } catch (error) { 18 | logError(error.message, error); 19 | throw error; 20 | } 21 | }, 22 | }; 23 | 24 | export default command; 25 | -------------------------------------------------------------------------------- /packages/snaps-cli/src/cmds/manifest/manifest.e2e.test.ts: -------------------------------------------------------------------------------- 1 | import { run } from '../../test-utils'; 2 | 3 | describe('mm-snap manifest', () => { 4 | it.each(['manifest', 'm'])( 5 | 'validates the manifest using "mm-snap %s"', 6 | async (command) => { 7 | await run({ 8 | command, 9 | }) 10 | .code(0) 11 | .end(); 12 | }, 13 | ); 14 | }); 15 | -------------------------------------------------------------------------------- /packages/snaps-cli/src/cmds/serve/index.ts: -------------------------------------------------------------------------------- 1 | import yargs from 'yargs'; 2 | 3 | import builders from '../../builders'; 4 | import { YargsArgs } from '../../types/yargs'; 5 | import { serve } from './serveHandler'; 6 | 7 | const command = { 8 | command: ['serve', 's'], 9 | desc: 'Locally serve Snap file(s) for testing', 10 | builder: (yarg: yargs.Argv) => { 11 | yarg.option('root', builders.root).option('port', builders.port); 12 | }, 13 | handler: async (argv: YargsArgs) => serve(argv), 14 | }; 15 | 16 | export default command; 17 | -------------------------------------------------------------------------------- /packages/snaps-cli/src/index.ts: -------------------------------------------------------------------------------- 1 | export * as utils from './utils'; 2 | -------------------------------------------------------------------------------- /packages/snaps-cli/src/main.test.ts: -------------------------------------------------------------------------------- 1 | import * as cliModule from './cli'; 2 | import commands from './cmds'; 3 | 4 | jest.mock('./cli', () => ({ 5 | cli: jest.fn(), 6 | })); 7 | 8 | describe('main', () => { 9 | it('executes the CLI application', async () => { 10 | await import('./main'); 11 | expect(cliModule.cli).toHaveBeenCalledTimes(1); 12 | expect(cliModule.cli).toHaveBeenCalledWith(process.argv, commands); 13 | expect(global.snaps).toStrictEqual({ 14 | // see test/setup.js 15 | verboseErrors: false, 16 | suppressWarnings: false, 17 | isWatching: false, 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/snaps-cli/src/main.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { cli } from './cli'; 4 | import commands from './cmds'; 5 | 6 | global.snaps = { 7 | verboseErrors: false, 8 | suppressWarnings: false, 9 | isWatching: false, 10 | }; 11 | 12 | cli(process.argv, commands); 13 | -------------------------------------------------------------------------------- /packages/snaps-cli/src/test-utils/fs.ts: -------------------------------------------------------------------------------- 1 | import { promises as fs } from 'fs'; 2 | 3 | jest.mock('fs'); 4 | 5 | /** 6 | * Clears out all the files in the in-memory file system, and writes the default 7 | * folders to mimic the on-disk current working directory, including sub-folders. 8 | */ 9 | export async function resetFileSystem() { 10 | await fs.rm(process.cwd(), { recursive: true, force: true }); 11 | 12 | // Using relative path with memfs won't work since process.cwd() specifies the cwd of the on-disk file system 13 | // This recursively creates the current working directory in the memfs volume. 14 | // Ref. https://github.com/streamich/memfs/blob/master/docs/relative-paths.md 15 | await fs.mkdir(process.cwd(), { recursive: true }); 16 | } 17 | -------------------------------------------------------------------------------- /packages/snaps-cli/src/test-utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './e2e'; 2 | export * from './fs'; 3 | -------------------------------------------------------------------------------- /packages/snaps-cli/src/types/snaps-cli.d.ts: -------------------------------------------------------------------------------- 1 | // We can't do "declare global" in this file without this, or else we get the 2 | // TS2669 error. 3 | // Kudos to: https://stackoverflow.com/a/59499895 4 | export {}; 5 | 6 | type SnapsCliGlobals = { 7 | verboseErrors?: boolean; 8 | suppressWarnings?: boolean; 9 | isWatching?: boolean; 10 | }; 11 | 12 | declare global { 13 | // eslint-disable-next-line no-var 14 | var snaps: SnapsCliGlobals; 15 | } 16 | -------------------------------------------------------------------------------- /packages/snaps-cli/src/types/yargs.d.ts: -------------------------------------------------------------------------------- 1 | import { Options } from 'yargs'; 2 | 3 | // eslint-disable-next-line @typescript-eslint/ban-types 4 | type OptionalArguments = T & { 5 | /** Non-option arguments */ 6 | _?: (string | number)[]; 7 | 8 | /** The script name or node command */ 9 | $0?: string; 10 | 11 | /** All remaining options */ 12 | [argName: string]: unknown; 13 | }; 14 | 15 | type YargsArgs = { 16 | sourceMaps: boolean; 17 | stripComments: boolean; 18 | transformHtmlComments: boolean; 19 | port: number; 20 | dist: string; 21 | src: string; 22 | eval: boolean; 23 | outfileName: string; 24 | serve: boolean; 25 | directory?: string; 26 | } & OptionalArguments; 27 | 28 | type Option = { 29 | stripComments: boolean; 30 | transformHtmlComments: boolean; 31 | } & Options; 32 | -------------------------------------------------------------------------------- /packages/snaps-cli/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './misc'; 2 | export * from './snap-config'; 3 | -------------------------------------------------------------------------------- /packages/snaps-cli/test/setup.js: -------------------------------------------------------------------------------- 1 | global.snaps = { 2 | verboseErrors: false, 3 | suppressWarnings: false, 4 | isWatching: false, 5 | }; 6 | -------------------------------------------------------------------------------- /packages/snaps-cli/test/snap/README.md: -------------------------------------------------------------------------------- 1 | # CLI Test Snap 2 | 3 | This is a test snap for `@metamask/snaps-cli`. It's used to end-to-end test the 4 | CLI commands. 5 | -------------------------------------------------------------------------------- /packages/snaps-cli/test/snap/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@metamask/cli-test-snap", 3 | "version": "0.34.1-flask.1", 4 | "private": true, 5 | "description": "A snap for end-to-end testing the MetaMask Snaps CLI.", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/MetaMask/snaps.git" 9 | }, 10 | "scripts": { 11 | "build": "mm-snap build" 12 | }, 13 | "dependencies": { 14 | "@metamask/snaps-types": "workspace:^" 15 | }, 16 | "devDependencies": { 17 | "@metamask/snaps-cli": "workspace:^" 18 | }, 19 | "packageManager": "yarn@3.4.1" 20 | } 21 | -------------------------------------------------------------------------------- /packages/snaps-cli/test/snap/snap.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cliOptions: { 3 | src: './src/index.ts', 4 | port: 34889, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/snaps-cli/test/snap/snap.manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.34.1-flask.1", 3 | "description": "A snap for end-to-end testing the MetaMask Snaps CLI.", 4 | "proposedName": "CLI Test Snap", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/MetaMask/snaps.git" 8 | }, 9 | "source": { 10 | "shasum": "ElvJRk3W6Uqa6do/SoM5muRfvLLL156Uo/Lu/77a49Q=", 11 | "location": { 12 | "npm": { 13 | "filePath": "dist/bundle.js", 14 | "iconPath": "images/icon.svg", 15 | "packageName": "@metamask/cli-test-snap", 16 | "registry": "https://registry.npmjs.org/" 17 | } 18 | } 19 | }, 20 | "initialPermissions": { 21 | "endowment:rpc": { 22 | "dapps": true 23 | }, 24 | "snap_dialog": {} 25 | }, 26 | "manifestVersion": "0.1" 27 | } 28 | -------------------------------------------------------------------------------- /packages/snaps-cli/test/snap/src/index.ts: -------------------------------------------------------------------------------- 1 | import { OnRpcRequestHandler } from '@metamask/snaps-types'; 2 | 3 | export const onRpcRequest: OnRpcRequestHandler = async () => { 4 | return 'Hello, world!'; 5 | }; 6 | -------------------------------------------------------------------------------- /packages/snaps-cli/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.build.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/types", 6 | "rootDir": "./src" 7 | }, 8 | "include": ["./src"], 9 | "exclude": [ 10 | "**/*.test.ts", 11 | "./src/**/test-utils", 12 | "./src/**/__mocks__", 13 | "./src/**/__snapshots__" 14 | ], 15 | "references": [ 16 | { "path": "../snaps-utils/tsconfig.build.json" }, 17 | { "path": "../snaps-browserify-plugin/tsconfig.build.json" } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /packages/snaps-cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.json", 3 | "compilerOptions": { 4 | "baseUrl": "./" 5 | }, 6 | "include": ["./src", "./src/**/*.json", "test"], 7 | "references": [ 8 | { "path": "../snaps-utils" }, 9 | { "path": "../snaps-browserify-plugin" }, 10 | { "path": "../snaps-types" } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /packages/snaps-controllers/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | 8 | rules: { 9 | '@typescript-eslint/consistent-type-definitions': 'off', 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /packages/snaps-controllers/README.md: -------------------------------------------------------------------------------- 1 | # @metamask/snaps-controllers 2 | 3 | Controllers for MetaMask Snaps functionality. 4 | -------------------------------------------------------------------------------- /packages/snaps-controllers/coverage.json: -------------------------------------------------------------------------------- 1 | { 2 | "branches": 88.52, 3 | "functions": 94.46, 4 | "lines": 96.16, 5 | "statements": 95.75 6 | } 7 | -------------------------------------------------------------------------------- /packages/snaps-controllers/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../jest.config.base'); 4 | 5 | delete baseConfig.coverageThreshold; 6 | 7 | module.exports = deepmerge(baseConfig, { 8 | coverageDirectory: './coverage/jest', 9 | testTimeout: 10000, 10 | 11 | // This is required for `jest-fetch-mock` to work. 12 | automock: false, 13 | resetMocks: false, 14 | restoreMocks: false, 15 | }); 16 | -------------------------------------------------------------------------------- /packages/snaps-controllers/scripts/generate-fixtures.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -x 4 | set -e 5 | set -u 6 | set -o pipefail 7 | 8 | # https://stackoverflow.com/questions/6393551/what-is-the-meaning-of-0-in-a-bash-script 9 | cd "${0%/*}" 10 | 11 | # Cleanup 12 | cd ../test/fixtures 13 | rm -f ./*.tgz 14 | # Download template-snap package tarball 15 | npm pack @metamask/template-snap 16 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/cronjob/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CronjobController'; 2 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/index.ts: -------------------------------------------------------------------------------- 1 | export type { Json } from '@metamask/utils'; 2 | export * from './services'; 3 | export * from './snaps'; 4 | export * from './utils'; 5 | export * from './cronjob'; 6 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/logging.ts: -------------------------------------------------------------------------------- 1 | import { snapsLogger } from '@metamask/snaps-utils'; 2 | import { createModuleLogger } from '@metamask/utils'; 3 | 4 | /** 5 | * A logging function specific to this package. The log messages don't show up 6 | * by default, but they can be enabled by setting the environment variable: 7 | * - `DEBUG=metamask:snaps:snaps-controllers`, or 8 | * - `DEBUG=metamask:snaps:*` to enable all logs from `@metamask/snaps-*`. 9 | */ 10 | export const log = createModuleLogger(snapsLogger, 'snaps-controllers'); 11 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/services/browser.test.ts: -------------------------------------------------------------------------------- 1 | import * as BrowserExport from './browser'; 2 | 3 | describe('browser entrypoint', () => { 4 | const expectedExports = [ 5 | 'AbstractExecutionService', 6 | 'setupMultiplex', 7 | 'IframeExecutionService', 8 | 'OffscreenExecutionService', 9 | 'WebWorkerExecutionService', 10 | 'ProxyPostMessageStream', 11 | ]; 12 | 13 | it('entrypoint has expected exports', () => { 14 | expect(Object.keys(BrowserExport)).toHaveLength(expectedExports.length); 15 | 16 | for (const exportName of expectedExports) { 17 | expect(exportName in BrowserExport).toBe(true); 18 | } 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/services/browser.ts: -------------------------------------------------------------------------------- 1 | // Subset of exports meant for browser environments, omits Node.js services 2 | export * from './AbstractExecutionService'; 3 | export * from './ExecutionService'; 4 | export * from './ProxyPostMessageStream'; 5 | export * from './iframe'; 6 | export * from './offscreen'; 7 | export { WebWorkerExecutionService } from './webworker'; 8 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/services/iframe/index.ts: -------------------------------------------------------------------------------- 1 | export * from './IframeExecutionService'; 2 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/services/index.ts: -------------------------------------------------------------------------------- 1 | export * from './AbstractExecutionService'; 2 | export * from './ExecutionService'; 3 | export * from './ProxyPostMessageStream'; 4 | export * from './iframe'; 5 | export * from './node'; 6 | export * from './offscreen'; 7 | export { WebWorkerExecutionService } from './webworker'; 8 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/services/node/index.ts: -------------------------------------------------------------------------------- 1 | export * from './NodeProcessExecutionService'; 2 | export * from './NodeThreadExecutionService'; 3 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/services/offscreen/index.ts: -------------------------------------------------------------------------------- 1 | export * from './OffscreenExecutionService'; 2 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/services/webworker/index.ts: -------------------------------------------------------------------------------- 1 | export * from './WebWorkerExecutionService'; 2 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/snaps/endowments/enum.ts: -------------------------------------------------------------------------------- 1 | export enum SnapEndowments { 2 | NetworkAccess = 'endowment:network-access', 3 | LongRunning = 'endowment:long-running', 4 | TransactionInsight = 'endowment:transaction-insight', 5 | Cronjob = 'endowment:cronjob', 6 | EthereumProvider = 'endowment:ethereum-provider', 7 | Rpc = 'endowment:rpc', 8 | WebAssemblyAccess = 'endowment:webassembly', 9 | } 10 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/snaps/endowments/long-running.test.ts: -------------------------------------------------------------------------------- 1 | import { PermissionType, SubjectType } from '@metamask/permission-controller'; 2 | 3 | import { SnapEndowments } from '.'; 4 | import { longRunningEndowmentBuilder } from './long-running'; 5 | 6 | describe('endowment:long-running', () => { 7 | it('builds the expected permission specification', () => { 8 | const specification = longRunningEndowmentBuilder.specificationBuilder({}); 9 | expect(specification).toStrictEqual({ 10 | permissionType: PermissionType.Endowment, 11 | targetName: SnapEndowments.LongRunning, 12 | endowmentGetter: expect.any(Function), 13 | allowedCaveats: null, 14 | subjectTypes: [SubjectType.Snap], 15 | }); 16 | 17 | expect(specification.endowmentGetter()).toBeUndefined(); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/snaps/index.ts: -------------------------------------------------------------------------------- 1 | export * from './location'; 2 | export * from './SnapController'; 3 | export * from './endowments'; 4 | export * from './selectors'; 5 | export * from './registry'; 6 | export * from './permissions'; 7 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/snaps/location/index.ts: -------------------------------------------------------------------------------- 1 | export * from './location'; 2 | export * from './npm'; 3 | export * from './local'; 4 | export * from './http'; 5 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/snaps/registry/index.ts: -------------------------------------------------------------------------------- 1 | export * from './registry'; 2 | export * from './json'; 3 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/snaps/selectors.ts: -------------------------------------------------------------------------------- 1 | import { TruncatedSnap } from '@metamask/snaps-utils'; 2 | 3 | export const getRunnableSnaps = (snaps: T[]) => 4 | snaps.filter((snap) => snap.enabled && !snap.blocked); 5 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/test-utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './controller'; 2 | export * from './execution-environment'; 3 | export * from './service'; 4 | export * from './sleep'; 5 | export * from './location'; 6 | export * from './registry'; 7 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/test-utils/registry.ts: -------------------------------------------------------------------------------- 1 | import { SnapsRegistry, SnapsRegistryStatus } from '../snaps'; 2 | 3 | export class MockSnapsRegistry implements SnapsRegistry { 4 | get = jest.fn().mockImplementation(async (snaps) => { 5 | return Promise.resolve( 6 | Object.keys(snaps).reduce( 7 | (acc, snapId) => ({ 8 | ...acc, 9 | [snapId]: { status: SnapsRegistryStatus.Unverified }, 10 | }), 11 | {}, 12 | ), 13 | ); 14 | }); 15 | 16 | getMetadata = jest.fn().mockResolvedValue(null); 17 | } 18 | -------------------------------------------------------------------------------- /packages/snaps-controllers/src/test-utils/sleep.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Get a promise that resolves after a given number of milliseconds. 3 | * 4 | * @param ms - The number of milliseconds to sleep. 5 | * @returns A promise that resolves after the given number of milliseconds. 6 | */ 7 | export async function sleep(ms: number): Promise { 8 | return new Promise((resolve) => setTimeout(resolve, ms)); 9 | } 10 | -------------------------------------------------------------------------------- /packages/snaps-controllers/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.build.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/types", 6 | "rootDir": "./src" 7 | }, 8 | "include": ["./src"], 9 | "exclude": [ 10 | "**/*.test.ts", 11 | "**/*.test.browser.ts", 12 | "./src/**/test-utils", 13 | "./src/**/__mocks__", 14 | "./src/**/__snapshots__", 15 | "wdio.config.ts", 16 | "scripts" 17 | ], 18 | "references": [ 19 | { 20 | "path": "../snaps-utils/tsconfig.build.json" 21 | }, 22 | { 23 | "path": "../rpc-methods/tsconfig.build.json" 24 | }, 25 | { 26 | "path": "../snaps-execution-environments/tsconfig.build.json" 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /packages/snaps-controllers/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.json", 3 | "compilerOptions": { 4 | "baseUrl": "./" 5 | }, 6 | "include": ["./src", "wdio.config.ts", "scripts"], 7 | "references": [ 8 | { "path": "../snaps-execution-environments" }, 9 | { "path": "../rpc-methods" }, 10 | { "path": "../snaps-utils" } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /packages/snaps-controllers/tsconfig.local.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "composite": false 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | 8 | overrides: [ 9 | { 10 | files: ['*.test.ts'], 11 | rules: { 12 | 'jsdoc/check-tag-names': [ 13 | 'error', 14 | { 15 | definedTags: ['jest-environment'], 16 | }, 17 | ], 18 | }, 19 | }, 20 | ], 21 | 22 | ignorePatterns: ['src/openrpc.json', 'webpack.config.js', '__test__'], 23 | }; 24 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | coverage 4 | coverage-ava 5 | coverage-all 6 | coverage-merged 7 | dist 8 | dist-temp 9 | temp 10 | *.log 11 | *.tgz 12 | *.ava.test.ts.md 13 | 14 | public/ 15 | src/__GENERATED__/ 16 | __test__ 17 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/README.md: -------------------------------------------------------------------------------- 1 | # @metamask/snaps-execution-environments 2 | 3 | Execution environments for [MetaMask Snaps](https://docs.metamask.io/guide/snaps.html), sandboxed using [Secure EcmaScript (SES)](https://github.com/endojs/endo/tree/master/packages/ses). 4 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/coverage.json: -------------------------------------------------------------------------------- 1 | { 2 | "branches": 77.37, 3 | "functions": 91.91, 4 | "lines": 90.46, 5 | "statements": 90.35 6 | } 7 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../jest.config.base'); 4 | 5 | delete baseConfig.coverageThreshold; 6 | 7 | module.exports = deepmerge(baseConfig, { 8 | coveragePathIgnorePatterns: [ 9 | './src/index.ts', 10 | './src/iframe/index.ts', 11 | './src/offscreen/index.ts', 12 | './src/webworker/executor/index.ts', 13 | './src/webworker/pool/index.ts', 14 | './src/common/test-utils', 15 | ], 16 | coverageDirectory: './coverage/jest', 17 | testTimeout: 10000, 18 | testEnvironment: '/jest.environment.js', 19 | testEnvironmentOptions: { 20 | customExportConditions: ['node', 'node-addons'], 21 | }, 22 | 23 | // This is required for `jest-fetch-mock` to work. 24 | resetMocks: false, 25 | }); 26 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/jest.environment.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | const { TestEnvironment } = require('jest-environment-node'); 3 | 4 | // Custom test environment copied from https://github.com/jsdom/jsdom/issues/2524 5 | // in order to add TextEncoder to jsdom. TextEncoder is expected by jose. 6 | 7 | module.exports = class CustomTestEnvironment extends TestEnvironment { 8 | async setup() { 9 | await super.setup(); 10 | 11 | this.global.harden = (param) => param; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/lavamoat/browserify/policy-override.json: -------------------------------------------------------------------------------- 1 | { 2 | "resources": { 3 | "external:../snaps-utils/src/icon.ts": { 4 | "builtin": { 5 | "buffer": true 6 | } 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/lavamoat/build-system/policy-override.json: -------------------------------------------------------------------------------- 1 | { 2 | "resources": { 3 | "lavamoat-browserify": { 4 | "builtin": { 5 | "node:module": true 6 | } 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/src/common/endowments/textDecoder.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Creates TextDecoder function hardened by SES. 3 | * 4 | * @returns An object with the attenuated `TextDecoder` function. 5 | */ 6 | const createTextDecoder = () => { 7 | return { 8 | TextDecoder: harden(TextDecoder), 9 | } as const; 10 | }; 11 | 12 | const endowmentModule = { 13 | names: ['TextDecoder'] as const, 14 | factory: createTextDecoder, 15 | }; 16 | export default endowmentModule; 17 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/src/common/endowments/textEncoder.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Creates TextEncoder function hardened by SES. 3 | * 4 | * @returns An object with the attenuated `TextEncoder` function. 5 | */ 6 | const createTextEncoder = () => { 7 | return { 8 | TextEncoder: harden(TextEncoder), 9 | } as const; 10 | }; 11 | 12 | const endowmentModule = { 13 | names: ['TextEncoder'] as const, 14 | factory: createTextEncoder, 15 | }; 16 | export default endowmentModule; 17 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/src/common/globalObject.test.ts: -------------------------------------------------------------------------------- 1 | import { rootRealmGlobal, rootRealmGlobalName } from './globalObject'; 2 | 3 | describe('globalObject', () => { 4 | it('has the expected values', () => { 5 | expect(rootRealmGlobal).toStrictEqual(globalThis); 6 | expect(rootRealmGlobalName).toBe('globalThis'); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/src/common/test-utils/logger.ts: -------------------------------------------------------------------------------- 1 | import { ConsoleLike } from '@metamask/providers/dist/utils'; 2 | 3 | export const SILENT_LOGGER: ConsoleLike = { 4 | log: () => undefined, 5 | warn: () => undefined, 6 | error: () => undefined, 7 | debug: () => undefined, 8 | info: () => undefined, 9 | trace: () => undefined, 10 | }; 11 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/src/globals.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/unambiguous */ 2 | // Typescript doesn't type WeakRef on ES2020, only on ESNext 3 | // But it's supported on all browsers and Node 4 | // Note, it's stated that it's not supported on Opera, 5 | // But that's not true - https://github.com/mdn/browser-compat-data/issues/12523 6 | declare class WeakRef { 7 | constructor(target: T); 8 | 9 | deref(): T | undefined; 10 | } 11 | 12 | // Typescript doesn't type FinalizationRegistry on ES2020, only on ESNext 13 | declare class FinalizationRegistry { 14 | constructor(callbackFn: (value: T) => void); 15 | 16 | register(obj: any, value: T, unregisterToken?: unknown): void; 17 | 18 | unregister(unregisterToken: unknown): void; 19 | } 20 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/src/iframe/index.ts: -------------------------------------------------------------------------------- 1 | import { executeLockdownEvents } from '../common/lockdown/lockdown-events'; 2 | import { executeLockdownMore } from '../common/lockdown/lockdown-more'; 3 | import { IFrameSnapExecutor } from './IFrameSnapExecutor'; 4 | 5 | // Lockdown is already applied in LavaMoat 6 | executeLockdownMore(); 7 | executeLockdownEvents(); 8 | 9 | IFrameSnapExecutor.initialize(); 10 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/src/logging.ts: -------------------------------------------------------------------------------- 1 | import { snapsLogger } from '@metamask/snaps-utils'; 2 | import { createModuleLogger } from '@metamask/utils'; 3 | 4 | /** 5 | * A logging function specific to this package. The log messages don't show up 6 | * by default, but they can be enabled by setting the environment variable: 7 | * - `DEBUG=metamask:snaps:snaps-execution-environments`, or 8 | * - `DEBUG=metamask:snaps:*` to enable all logs from `@metamask/snaps-*`. 9 | */ 10 | export const log = createModuleLogger( 11 | snapsLogger, 12 | 'snaps-execution-environments', 13 | ); 14 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/src/node-process/index.ts: -------------------------------------------------------------------------------- 1 | import { executeLockdownMore } from '../common/lockdown/lockdown-more'; 2 | import { ChildProcessSnapExecutor } from './ChildProcessSnapExecutor'; 3 | 4 | // Lockdown is already applied in LavaMoat 5 | executeLockdownMore(); 6 | 7 | ChildProcessSnapExecutor.initialize(); 8 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/src/node-thread/index.ts: -------------------------------------------------------------------------------- 1 | import { executeLockdownMore } from '../common/lockdown/lockdown-more'; 2 | import { ThreadSnapExecutor } from './ThreadSnapExecutor'; 3 | 4 | // Lockdown is already applied in LavaMoat 5 | executeLockdownMore(); 6 | 7 | ThreadSnapExecutor.initialize(); 8 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/src/offscreen/index.ts: -------------------------------------------------------------------------------- 1 | import { BrowserRuntimePostMessageStream } from '@metamask/post-message-stream'; 2 | 3 | import { executeLockdownEvents } from '../common/lockdown/lockdown-events'; 4 | import { executeLockdownMore } from '../common/lockdown/lockdown-more'; 5 | import { OffscreenSnapExecutor } from './OffscreenSnapExecutor'; 6 | 7 | // Lockdown is already applied in LavaMoat 8 | executeLockdownMore(); 9 | executeLockdownEvents(); 10 | 11 | // The stream from the offscreen document to the execution service. 12 | const parentStream = new BrowserRuntimePostMessageStream({ 13 | name: 'child', 14 | target: 'parent', 15 | }); 16 | 17 | OffscreenSnapExecutor.initialize(parentStream); 18 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/src/webworker/executor/index.ts: -------------------------------------------------------------------------------- 1 | import { executeLockdownEvents } from '../../common/lockdown/lockdown-events'; 2 | import { executeLockdownMore } from '../../common/lockdown/lockdown-more'; 3 | import { WebWorkerSnapExecutor } from './WebWorkerSnapExecutor'; 4 | 5 | // Lockdown is already applied in LavaMoat 6 | executeLockdownMore(); 7 | executeLockdownEvents(); 8 | 9 | WebWorkerSnapExecutor.initialize(); 10 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/src/webworker/pool/index.ts: -------------------------------------------------------------------------------- 1 | import { executeLockdownEvents } from '../../common/lockdown/lockdown-events'; 2 | import { executeLockdownMore } from '../../common/lockdown/lockdown-more'; 3 | import { WebWorkerPool } from './WebWorkerPool'; 4 | 5 | // Lockdown is already applied in LavaMoat 6 | executeLockdownMore(); 7 | executeLockdownEvents(); 8 | 9 | WebWorkerPool.initialize(); 10 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.build.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/types", 6 | "rootDir": "./src", 7 | "typeRoots": ["../../node_modules/@types", "./node_modules/@types"] 8 | }, 9 | "include": ["./src", "./src/openrpc.json"], 10 | "exclude": [ 11 | "**/*.test.ts", 12 | "**/*.test.browser.ts", 13 | "./src/**/test-utils", 14 | "./src/**/__mocks__", 15 | "./src/**/__snapshots__", 16 | "wdio.config.ts", 17 | "scripts" 18 | ], 19 | "references": [ 20 | { 21 | "path": "../rpc-methods/tsconfig.build.json" 22 | }, 23 | { 24 | "path": "../snaps-utils/tsconfig.build.json" 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /packages/snaps-execution-environments/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "typeRoots": ["../../node_modules/@types", "./node_modules/@types"], 6 | "allowJs": true 7 | }, 8 | "include": [ 9 | "./src", 10 | "./src/openrpc.json", 11 | "webpack.config.js", 12 | "wdio.config.ts", 13 | "scripts" 14 | ], 15 | "references": [ 16 | { 17 | "path": "../rpc-methods" 18 | }, 19 | { 20 | "path": "../snaps-utils" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/snaps-jest/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | 8 | ignorePatterns: ['public/'], 9 | }; 10 | -------------------------------------------------------------------------------- /packages/snaps-jest/.gitignore: -------------------------------------------------------------------------------- 1 | public 2 | -------------------------------------------------------------------------------- /packages/snaps-jest/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | [Unreleased]: https://github.com/MetaMask/snaps/ 10 | -------------------------------------------------------------------------------- /packages/snaps-jest/jest-preset.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable jsdoc/valid-types */ 2 | 3 | const { resolve } = require('path'); 4 | 5 | /** 6 | * @type {import('jest').Config} 7 | */ 8 | const config = { 9 | testEnvironment: '@metamask/snaps-jest', 10 | 11 | // End-to-end tests can take longer than usual to run, so we set the test 12 | // timeout to 30 seconds by default. 13 | testTimeout: 30000, 14 | 15 | setupFilesAfterEnv: [resolve(__dirname, 'dist', 'cjs', 'setup.js')], 16 | }; 17 | 18 | module.exports = config; 19 | -------------------------------------------------------------------------------- /packages/snaps-jest/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | coverageThreshold: { 7 | global: { 8 | branches: 0, 9 | functions: 0, 10 | lines: 0, 11 | statements: 0, 12 | }, 13 | }, 14 | }); 15 | -------------------------------------------------------------------------------- /packages/snaps-jest/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default, default as TestEnvironment } from './environment'; 2 | export * from './helpers'; 3 | export * from './options'; 4 | export * from './types'; 5 | -------------------------------------------------------------------------------- /packages/snaps-jest/src/internals/environment.ts: -------------------------------------------------------------------------------- 1 | import { assert } from '@metamask/utils'; 2 | 3 | /** 4 | * Get the Snaps environment. This asserts that the environment has been 5 | * configured. 6 | * 7 | * @returns The Snaps environment. 8 | */ 9 | export function getEnvironment() { 10 | // `snapsEnvironment` is a global variable that is set by the Jest 11 | // environment. 12 | assert( 13 | snapsEnvironment, 14 | 'Snaps environment not found. Make sure you have configured the environment correctly.', 15 | ); 16 | 17 | return snapsEnvironment; 18 | } 19 | -------------------------------------------------------------------------------- /packages/snaps-jest/src/internals/index.ts: -------------------------------------------------------------------------------- 1 | export * from './environment'; 2 | export * from './interface'; 3 | export * from './logger'; 4 | export * from './network'; 5 | export * from './request'; 6 | export * from './server'; 7 | export * from './structs'; 8 | // eslint-disable-next-line import/export 9 | export * from './types'; 10 | export * from './wait-for'; 11 | -------------------------------------------------------------------------------- /packages/snaps-jest/src/internals/logger.ts: -------------------------------------------------------------------------------- 1 | import { createProjectLogger } from '@metamask/utils'; 2 | 3 | export const rootLogger = createProjectLogger('snaps-jest'); 4 | -------------------------------------------------------------------------------- /packages/snaps-jest/src/setup.ts: -------------------------------------------------------------------------------- 1 | // Setup file for Jest. This file is used in the Jest preset configuration, and 2 | // not intended to be exported or used directly. 3 | 4 | // eslint-disable-next-line import/no-unassigned-import 5 | import './matchers'; 6 | -------------------------------------------------------------------------------- /packages/snaps-jest/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.build.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/types", 6 | "rootDir": "./src", 7 | "jsx": "preserve" 8 | }, 9 | "include": ["./src"], 10 | "exclude": [ 11 | "**/*.test.ts", 12 | "./src/**/test-utils", 13 | "./src/**/__mocks__", 14 | "./src/**/__snapshots__" 15 | ], 16 | "references": [ 17 | { 18 | "path": "../snaps-utils/tsconfig.build.json" 19 | }, 20 | { 21 | "path": "../snaps-simulator/tsconfig.build.json" 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /packages/snaps-jest/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "jsx": "preserve" 6 | }, 7 | "include": ["./src"], 8 | "references": [ 9 | { 10 | "path": "../rpc-methods" 11 | }, 12 | { 13 | "path": "../snaps-utils" 14 | }, 15 | { 16 | "path": "../snaps-simulator" 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /packages/snaps-rollup-plugin/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/snaps-rollup-plugin/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | dist 4 | dist-temp 5 | temp 6 | *.log 7 | *.tgz 8 | 9 | public/ 10 | src/__GENERATED__/ 11 | -------------------------------------------------------------------------------- /packages/snaps-rollup-plugin/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2022 MetaMask 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /packages/snaps-rollup-plugin/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | coveragePathIgnorePatterns: ['./src/__fixtures__'], 7 | coverageThreshold: { 8 | global: { 9 | branches: 100, 10 | functions: 100, 11 | lines: 100, 12 | statements: 100, 13 | }, 14 | }, 15 | }); 16 | -------------------------------------------------------------------------------- /packages/snaps-rollup-plugin/src/__fixtures__/source-map.ts: -------------------------------------------------------------------------------- 1 | // This file is only used for testing source map generation. 2 | 3 | // eslint-disable-next-line import/unambiguous 4 | const foo = 'bar'; 5 | // eslint-disable-next-line no-console 6 | console.log(foo); 7 | -------------------------------------------------------------------------------- /packages/snaps-rollup-plugin/src/__mocks__/fs.ts: -------------------------------------------------------------------------------- 1 | import { Volume } from 'memfs'; 2 | 3 | // Note: `Volume` implements most of the `fs` API, but not all. 4 | export = new Volume(); 5 | -------------------------------------------------------------------------------- /packages/snaps-rollup-plugin/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './plugin'; 2 | export type { Options } from './plugin'; 3 | -------------------------------------------------------------------------------- /packages/snaps-rollup-plugin/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.build.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/types", 6 | "rootDir": "./src" 7 | }, 8 | "include": ["./src"], 9 | "exclude": [ 10 | "**/*.test.ts", 11 | "./src/**/test-utils", 12 | "./src/**/__mocks__", 13 | "./src/**/__snapshots__" 14 | ], 15 | "references": [ 16 | { 17 | "path": "../snaps-utils/tsconfig.build.json" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/snaps-rollup-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.json", 3 | "compilerOptions": { 4 | "baseUrl": "./" 5 | }, 6 | "include": ["./src"], 7 | "references": [{ "path": "../snaps-utils" }] 8 | } 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/.gitignore: -------------------------------------------------------------------------------- 1 | # Webpack vendor 2 | vendor 3 | -------------------------------------------------------------------------------- /packages/snaps-simulator/.swcrc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/swcrc", 3 | "jsc": { 4 | "parser": { 5 | "syntax": "typescript", 6 | "tsx": true 7 | }, 8 | "transform": { 9 | "react": { 10 | "runtime": "automatic" 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/snaps-simulator/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /packages/snaps-simulator/jest.environment.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | const { TestEnvironment } = require('jest-environment-jsdom'); 3 | 4 | // Custom test environment copied from https://github.com/jsdom/jsdom/issues/2524 5 | // in order to add TextEncoder to jsdom. TextEncoder is expected by jose. 6 | 7 | module.exports = class CustomTestEnvironment extends TestEnvironment { 8 | async setup() { 9 | await super.setup(); 10 | if (typeof this.global.TextEncoder === 'undefined') { 11 | const { TextEncoder, TextDecoder } = require('util'); 12 | this.global.TextEncoder = TextEncoder; 13 | this.global.TextDecoder = TextDecoder; 14 | this.global.ArrayBuffer = ArrayBuffer; 15 | this.global.Uint8Array = Uint8Array; 16 | } 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /packages/snaps-simulator/jest.setup.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | Object.defineProperty(window, 'matchMedia', { 3 | writable: true, 4 | value: (query) => ({ 5 | matches: false, 6 | media: query, 7 | onchange: null, 8 | addListener: jest.fn(), // deprecated 9 | removeListener: jest.fn(), // deprecated 10 | addEventListener: jest.fn(), 11 | removeEventListener: jest.fn(), 12 | dispatchEvent: jest.fn(), 13 | }), 14 | }); 15 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '@testing-library/react'; 2 | import fetchMock from 'jest-fetch-mock'; 3 | 4 | import { App } from './App'; 5 | import { Root } from './components'; 6 | import { createStore } from './store'; 7 | 8 | describe('App', () => { 9 | it('renders', () => { 10 | // This polyfills Request which seems to be missing in the Jest testing environment. 11 | fetchMock.enableMocks(); 12 | expect(() => 13 | render( 14 | 15 | 16 | , 17 | ), 18 | ).not.toThrow(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { FunctionComponent, useEffect } from 'react'; 2 | import { RouterProvider } from 'react-router-dom'; 3 | 4 | import { setSnapId } from './features'; 5 | import { useDispatch } from './hooks'; 6 | import { router } from './routes'; 7 | 8 | export const App: FunctionComponent = () => { 9 | const dispatch = useDispatch(); 10 | useEffect(() => { 11 | // Dispatch to start polling the default URL 12 | dispatch(setSnapId('local:http://localhost:8080')); 13 | }, [dispatch]); 14 | return ; 15 | }; 16 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/assets/file-mock.ts: -------------------------------------------------------------------------------- 1 | const fileMock = 'test-file-stub'; 2 | export default fileMock; 3 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/assets/fonts/EuclidCircularB-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alammonsur2/snaps/29981d1088a6a8e771739876a69eb86b2b96c1b4/packages/snaps-simulator/src/assets/fonts/EuclidCircularB-Bold.woff2 -------------------------------------------------------------------------------- /packages/snaps-simulator/src/assets/fonts/EuclidCircularB-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alammonsur2/snaps/29981d1088a6a8e771739876a69eb86b2b96c1b4/packages/snaps-simulator/src/assets/fonts/EuclidCircularB-Regular.woff2 -------------------------------------------------------------------------------- /packages/snaps-simulator/src/assets/fonts/IBMPlexMono-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alammonsur2/snaps/29981d1088a6a8e771739876a69eb86b2b96c1b4/packages/snaps-simulator/src/assets/fonts/IBMPlexMono-Regular.woff2 -------------------------------------------------------------------------------- /packages/snaps-simulator/src/assets/fonts/fonts.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Euclid Circular B'; 3 | font-style: normal; 4 | font-weight: 400; 5 | src: url('./EuclidCircularB-Regular.woff2') format('woff2'); 6 | } 7 | 8 | @font-face { 9 | font-family: 'Euclid Circular B'; 10 | font-style: normal; 11 | font-weight: 700; 12 | src: url('./EuclidCircularB-Bold.woff2') format('woff2'); 13 | } 14 | 15 | @font-face { 16 | font-family: 'IBM Plex Mono'; 17 | font-style: normal; 18 | font-weight: 400; 19 | src: url('./IBMPlexMono-Regular.woff2') format('woff2'); 20 | } 21 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/assets/icons/arrow-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/assets/icons/arrow-top-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/assets/icons/copy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/assets/icons/cross-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/assets/icons/cross.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/assets/icons/dark-arrow-top-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/assets/icons/divider.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/assets/icons/dot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/assets/icons/heading.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/assets/icons/play-muted.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/assets/icons/play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/components/Author.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../utils'; 2 | import { Author } from './Author'; 3 | 4 | describe('Author', () => { 5 | it('renders', () => { 6 | expect(() => 7 | render( 8 | , 9 | ), 10 | ).not.toThrow(); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/components/Icon.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../utils'; 2 | import { Icon } from './Icon'; 3 | 4 | describe('Icon', () => { 5 | it('renders', () => { 6 | expect(() => render()).not.toThrow(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/components/Link.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../utils'; 2 | import { Link } from './Link'; 3 | 4 | describe('Link', () => { 5 | it('renders', () => { 6 | expect(() => render()).not.toThrow(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/components/Logo.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../utils'; 2 | import { Logo } from './Logo'; 3 | 4 | describe('Logo', () => { 5 | it('renders', () => { 6 | expect(() => render()).not.toThrow(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/components/Logo.tsx: -------------------------------------------------------------------------------- 1 | import { Image, useColorMode } from '@chakra-ui/react'; 2 | import { FunctionComponent } from 'react'; 3 | 4 | import logoDark from '../assets/logo-dark.svg'; 5 | import logo from '../assets/logo.svg'; 6 | 7 | /** 8 | * Render the Snaps Simulator logo. 9 | * 10 | * @returns A React component. 11 | */ 12 | export const Logo: FunctionComponent = () => { 13 | const { colorMode } = useColorMode(); 14 | return ( 15 | MetaMask Snaps Simulator 20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/components/Prefill.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../utils'; 2 | import { Prefill } from './Prefill'; 3 | 4 | describe('Prefill', () => { 5 | it('renders', () => { 6 | expect(() => render(Prefill)).not.toThrow(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/components/SnapIcon.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../utils'; 2 | import { SnapIcon } from './SnapIcon'; 3 | 4 | describe('SnapIcon', () => { 5 | it('renders', () => { 6 | expect(() => render()).not.toThrow(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/components/TestConditional.tsx: -------------------------------------------------------------------------------- 1 | import { FunctionComponent, ReactNode } from 'react'; 2 | 3 | import { IS_TEST_BUILD } from '../utils'; 4 | 5 | export type TestProps = { 6 | children: ReactNode; 7 | isTest?: boolean; 8 | }; 9 | 10 | /** 11 | * Renders the children only if the build is a test build. 12 | * 13 | * @param props - The props. 14 | * @param props.children - The children to render. 15 | * @param props.isTest - Whether to render only in test builds, or only in non-test 16 | * builds. 17 | * @returns The component. 18 | */ 19 | export const TestConditional: FunctionComponent = ({ 20 | children, 21 | isTest = true, 22 | }) => { 23 | if (IS_TEST_BUILD === isTest) { 24 | return <>{children}; 25 | } 26 | 27 | return null; 28 | }; 29 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/components/Window.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../utils'; 2 | import { Window } from './Window'; 3 | 4 | describe('Window', () => { 5 | it('renders', () => { 6 | expect(() => 7 | render( 8 | 9 | Foo 10 | , 11 | ), 12 | ).not.toThrow(); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/components/dialogs/AlertDialog.test.tsx: -------------------------------------------------------------------------------- 1 | import { panel } from '@metamask/snaps-ui'; 2 | 3 | import { render } from '../../utils'; 4 | import { AlertDialog } from './AlertDialog'; 5 | 6 | describe('AlertDialog', () => { 7 | it('renders', () => { 8 | expect(() => 9 | render( 10 | , 15 | ), 16 | ).not.toThrow(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/components/dialogs/ConfirmationDialog.test.tsx: -------------------------------------------------------------------------------- 1 | import { panel } from '@metamask/snaps-ui'; 2 | 3 | import { render } from '../../utils'; 4 | import { ConfirmationDialog } from './ConfirmationDialog'; 5 | 6 | describe('ConfirmationDialog', () => { 7 | it('renders', () => { 8 | expect(() => 9 | render( 10 | , 15 | ), 16 | ).not.toThrow(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/components/dialogs/PromptDialog.test.tsx: -------------------------------------------------------------------------------- 1 | import { panel } from '@metamask/snaps-ui'; 2 | 3 | import { render } from '../../utils'; 4 | import { PromptDialog } from './PromptDialog'; 5 | 6 | describe('PromptDialog', () => { 7 | it('renders', () => { 8 | expect(() => 9 | render( 10 | , 15 | ), 16 | ).not.toThrow(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/components/dialogs/index.ts: -------------------------------------------------------------------------------- 1 | export * from './AlertDialog'; 2 | export * from './ConfirmationDialog'; 3 | export * from './PromptDialog'; 4 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/components/index.ts: -------------------------------------------------------------------------------- 1 | // Components that are used in multiple places in the app, such as components 2 | // that are used in multiple routes, can be exported here. Components that are 3 | // only used in one place, such as components that are only used in one route, 4 | // should be exported from their respective feature folder. 5 | 6 | export * from './dialogs'; 7 | export * from './Delineator'; 8 | export * from './Editor'; 9 | export * from './Icon'; 10 | export * from './Logo'; 11 | export * from './Prefill'; 12 | export * from './Root'; 13 | export * from './Link'; 14 | export * from './TestConditional'; 15 | export * from './Window'; 16 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/entry.tsx: -------------------------------------------------------------------------------- 1 | import { assert } from '@metamask/utils'; 2 | import { createRoot } from 'react-dom/client'; 3 | 4 | import { setWindowApi } from './api'; 5 | import { App } from './App'; 6 | import { Root } from './components'; 7 | import { createStore } from './store'; 8 | import { IS_TEST_BUILD } from './utils'; 9 | 10 | // eslint-disable-next-line import/no-unassigned-import 11 | import './assets/fonts/fonts.css'; 12 | 13 | const rootElement = document.getElementById('root'); 14 | assert(rootElement, 'Root element not found.'); 15 | 16 | const store = createStore(); 17 | const root = createRoot(rootElement); 18 | 19 | if (IS_TEST_BUILD) { 20 | setWindowApi(store); 21 | } 22 | 23 | root.render( 24 | 25 | 26 | , 27 | ); 28 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/builder/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './TemplateComponentList'; 2 | export * from './EditableNode'; 3 | export * from './Node'; 4 | export * from './NodeRenderer'; 5 | export * from './NodeTree'; 6 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/builder/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Builder'; 2 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/configuration/Configuration.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../../utils'; 2 | import { Configuration } from './Configuration'; 3 | 4 | describe('Configuration', () => { 5 | it('renders', () => { 6 | expect(() => render()).not.toThrow(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/configuration/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Configuration'; 2 | export * from './slice'; 3 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/console/ConsoleContent.tsx: -------------------------------------------------------------------------------- 1 | import { Text } from '@chakra-ui/react'; 2 | 3 | import { useSelector } from '../../hooks'; 4 | import { ConsoleEntryType, getConsoleEntries } from './slice'; 5 | 6 | export const ConsoleContent = () => { 7 | const entries = useSelector(getConsoleEntries); 8 | 9 | const colors = { 10 | [ConsoleEntryType.Log]: 'text.console', 11 | [ConsoleEntryType.Error]: 'text.error', 12 | }; 13 | 14 | return ( 15 | <> 16 | {entries.map((entry) => ( 17 | 24 | {entry.message} 25 | 26 | ))} 27 | 28 | ); 29 | }; 30 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/console/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Console'; 2 | export * from './slice'; 3 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/components/Handler.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../../../utils'; 2 | import { Handler } from './Handler'; 3 | 4 | describe('Handler', () => { 5 | it('renders', () => { 6 | expect(() => render(, '/handler/onRpcRequest')).not.toThrow(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/components/History.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../../../utils'; 2 | import { History } from './History'; 3 | 4 | describe('History', () => { 5 | it('renders', () => { 6 | expect(() => render(, '/handler/onRpcRequest')).not.toThrow(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/components/HistoryItem.test.tsx: -------------------------------------------------------------------------------- 1 | import { List, Tabs } from '@chakra-ui/react'; 2 | 3 | import { render } from '../../../utils'; 4 | import { HistoryItem } from './HistoryItem'; 5 | 6 | describe('HistoryItem', () => { 7 | it('renders', () => { 8 | expect(() => 9 | render( 10 | 11 | 12 | 13 | 14 | , 15 | '/handler/onRpcRequest', 16 | ), 17 | ).not.toThrow(); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/components/ResetTab.tsx: -------------------------------------------------------------------------------- 1 | import { useTabsContext } from '@chakra-ui/react'; 2 | import { FunctionComponent, useEffect } from 'react'; 3 | 4 | import { useHandler } from '../../../hooks'; 5 | 6 | /** 7 | * Resets the tab to the first tab when the handler changes. 8 | * 9 | * @returns `null`. 10 | */ 11 | export const ResetTab: FunctionComponent = () => { 12 | const handler = useHandler(); 13 | const tab = useTabsContext(); 14 | 15 | useEffect(() => { 16 | tab.setSelectedIndex(0); 17 | }, [handler, tab]); 18 | 19 | return null; 20 | }; 21 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/components/ResetUserInterfaceTab.tsx: -------------------------------------------------------------------------------- 1 | import { useTabsContext } from '@chakra-ui/react'; 2 | import { FunctionComponent, useEffect } from 'react'; 3 | 4 | import { useSelector } from '../../../hooks'; 5 | import { getUserInterface } from '../../simulation'; 6 | 7 | /** 8 | * Resets the tab to the first tab when the user interface is closed. 9 | * 10 | * @returns `null`. 11 | */ 12 | export const ResetUserInterfaceTab: FunctionComponent = () => { 13 | const userInterface = useSelector(getUserInterface); 14 | const tab = useTabsContext(); 15 | 16 | useEffect(() => { 17 | if (!userInterface) { 18 | tab.setSelectedIndex(0); 19 | } 20 | }, [userInterface, tab]); 21 | 22 | return null; 23 | }; 24 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/components/Response.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../../../utils'; 2 | import { Response } from './Response'; 3 | 4 | describe('Response', () => { 5 | it('renders', () => { 6 | expect(() => render(, '/handler/onRpcRequest')).not.toThrow(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/components/UserInterface.test.tsx: -------------------------------------------------------------------------------- 1 | import { Tabs } from '@chakra-ui/react'; 2 | 3 | import { render } from '../../../utils'; 4 | import { UserInterface } from './UserInterface'; 5 | 6 | describe('UserInterface', () => { 7 | it('renders', () => { 8 | expect(() => 9 | render( 10 | 11 | 12 | , 13 | '/handler/onRpcRequest', 14 | ), 15 | ).not.toThrow(); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Handler'; 2 | export * from './Response'; 3 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/cronjobs/Cronjobs.test.tsx: -------------------------------------------------------------------------------- 1 | import { Cronjobs } from './Cronjobs'; 2 | 3 | describe('Cronjobs', () => { 4 | it('renders', () => { 5 | expect(() => ).not.toThrow(); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/cronjobs/Cronjobs.tsx: -------------------------------------------------------------------------------- 1 | import { FunctionComponent } from 'react'; 2 | 3 | import { Request } from './components'; 4 | 5 | export const Cronjobs: FunctionComponent = () => ; 6 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/cronjobs/components/CronjobPrefill.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../../../../utils'; 2 | import { CronjobPrefill } from './CronjobPrefill'; 3 | 4 | describe('CronjobPrefill', () => { 5 | it('renders', () => { 6 | expect(() => 7 | render(), 8 | ).not.toThrow(); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/cronjobs/components/CronjobPrefill.tsx: -------------------------------------------------------------------------------- 1 | import { Json } from '@metamask/utils'; 2 | import { FunctionComponent } from 'react'; 3 | 4 | import { Prefill } from '../../../../components/Prefill'; 5 | 6 | export type CronjobData = { 7 | method: string; 8 | params?: Json | undefined; 9 | }; 10 | 11 | export type CronjobPrefillProps = CronjobData & { 12 | onClick: (prefill: CronjobData) => void; 13 | }; 14 | 15 | export const CronjobPrefill: FunctionComponent = ({ 16 | method, 17 | params, 18 | onClick, 19 | }) => { 20 | const handleClick = () => { 21 | onClick({ method, params }); 22 | }; 23 | 24 | return ( 25 | 26 | {method} 27 | 28 | ); 29 | }; 30 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/cronjobs/components/CronjobPrefills.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../../../../utils'; 2 | import { CronjobPrefills } from './CronjobPrefills'; 3 | 4 | describe('CronjobPrefills', () => { 5 | it('renders', () => { 6 | expect(() => render()).not.toThrow(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/cronjobs/components/Request.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../../../../utils'; 2 | import { Request } from './Request'; 3 | 4 | jest.mock('react-monaco-editor'); 5 | 6 | describe('Request', () => { 7 | it('renders', () => { 8 | expect(() => render()).not.toThrow(); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/cronjobs/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Request'; 2 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/cronjobs/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Cronjobs'; 2 | export * from './slice'; 3 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './components'; 2 | export { Cronjobs, cronjob } from './cronjobs'; 3 | export { JsonRpc, jsonRpc } from './json-rpc'; 4 | export { Transactions, transactions } from './transactions'; 5 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/json-rpc/JsonRpc.test.tsx: -------------------------------------------------------------------------------- 1 | import { JsonRpc } from './JsonRpc'; 2 | 3 | describe('JsonRpc', () => { 4 | it('renders', () => { 5 | expect(() => ).not.toThrow(); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/json-rpc/JsonRpc.tsx: -------------------------------------------------------------------------------- 1 | import { FunctionComponent } from 'react'; 2 | 3 | import { Request } from './components'; 4 | 5 | export const JsonRpc: FunctionComponent = () => ; 6 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/json-rpc/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Request'; 2 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/json-rpc/index.ts: -------------------------------------------------------------------------------- 1 | export * from './JsonRpc'; 2 | export * from './slice'; 3 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/transactions/Transactions.test.tsx: -------------------------------------------------------------------------------- 1 | import { Transactions } from './Transactions'; 2 | 3 | describe('Transactions', () => { 4 | it('renders', () => { 5 | expect(() => ).not.toThrow(); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/transactions/Transactions.tsx: -------------------------------------------------------------------------------- 1 | import { FunctionComponent } from 'react'; 2 | 3 | import { Request } from './components'; 4 | 5 | export const Transactions: FunctionComponent = () => ; 6 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/transactions/components/TransactionPrefill.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../../../../utils'; 2 | import { TRANSACTION_PRESETS } from '../presets'; 3 | import { TransactionPrefill } from './TransactionPrefill'; 4 | 5 | describe('TransactionPrefill', () => { 6 | it('renders', () => { 7 | expect(() => 8 | render( 9 | , 15 | ), 16 | ).not.toThrow(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/transactions/components/TransactionPrefill.tsx: -------------------------------------------------------------------------------- 1 | import { FunctionComponent } from 'react'; 2 | 3 | import { Prefill } from '../../../../components'; 4 | import { TransactionFormData } from '../utils'; 5 | 6 | export type TransactionPrefillProps = TransactionFormData & { 7 | name: string; 8 | onClick: (prefill: TransactionFormData) => void; 9 | }; 10 | 11 | export const TransactionPrefill: FunctionComponent = ({ 12 | name, 13 | onClick, 14 | ...transaction 15 | }) => { 16 | const handleClick = () => { 17 | onClick(transaction); 18 | }; 19 | 20 | return ( 21 | 22 | {name} 23 | 24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/transactions/components/TransactionPrefills.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../../../../utils'; 2 | import { TransactionPrefills } from './TransactionPrefills'; 3 | 4 | describe('TransactionPrefills', () => { 5 | it('renders', () => { 6 | expect(() => 7 | render(), 8 | ).not.toThrow(); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/transactions/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Request'; 2 | export * from './TransactionPrefills'; 3 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/handlers/transactions/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Transactions'; 2 | export * from './slice'; 3 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/index.library.ts: -------------------------------------------------------------------------------- 1 | export { JSON_RPC_ENDPOINT } from './simulation/index.library'; 2 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/index.ts: -------------------------------------------------------------------------------- 1 | export * from './builder'; 2 | export * from './handlers'; 3 | export * from './layout'; 4 | export * from './manifest'; 5 | export * from './navigation'; 6 | export * from './notifications'; 7 | export * from './simulation'; 8 | export * from './configuration'; 9 | export * from './polling'; 10 | export * from './console'; 11 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/layout/components/Header.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../../../utils'; 2 | import { Header } from './Header'; 3 | 4 | describe('Header', () => { 5 | it('renders', () => { 6 | expect(() => render(
)).not.toThrow(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/layout/components/Header.tsx: -------------------------------------------------------------------------------- 1 | import { Container, Stack } from '@chakra-ui/react'; 2 | import { FunctionComponent } from 'react'; 3 | 4 | import { Logo } from '../../../components'; 5 | import { Configuration } from '../../configuration'; 6 | import { StatusIndicator } from '../../status'; 7 | 8 | export const Header: FunctionComponent = () => ( 9 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ); 26 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/layout/components/Sidebar.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../../../utils'; 2 | import { Sidebar } from './Sidebar'; 3 | 4 | describe('Sidebar', () => { 5 | it('renders', () => { 6 | expect(() => render()).not.toThrow(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/layout/components/Sidebar.tsx: -------------------------------------------------------------------------------- 1 | import { Flex } from '@chakra-ui/react'; 2 | import { FunctionComponent } from 'react'; 3 | 4 | import { Navigation } from '../../navigation'; 5 | import { Bottom } from '../../navigation/components'; 6 | 7 | /** 8 | * The sidebar component, which holds the navigation buttons, etc. 9 | * 10 | * @returns The sidebar component. 11 | */ 12 | export const Sidebar: FunctionComponent = () => ( 13 | 14 | 15 | 16 | 17 | ); 18 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/layout/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Header'; 2 | export * from './Sidebar'; 3 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/layout/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Layout'; 2 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/manifest/Manifest.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../../utils'; 2 | import { Manifest } from './Manifest'; 3 | 4 | jest.mock('react-monaco-editor'); 5 | 6 | describe('Manifest', () => { 7 | it('renders', () => { 8 | expect(() => render()).not.toThrow(); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/manifest/components/Item.test.tsx: -------------------------------------------------------------------------------- 1 | import { List } from '@chakra-ui/react'; 2 | 3 | import { render } from '../../../utils'; 4 | import { Item } from './Item'; 5 | 6 | describe('Item', () => { 7 | it('renders', () => { 8 | expect(() => 9 | render( 10 | 11 | 12 | , 13 | ), 14 | ).not.toThrow(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/manifest/components/Validation.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../../../utils'; 2 | import { Validation } from './Validation'; 3 | 4 | describe('Validation', () => { 5 | it('renders', () => { 6 | expect(() => render()).not.toThrow(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/manifest/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Item'; 2 | export * from './Validation'; 3 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/manifest/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Manifest'; 2 | export * from './sagas'; 3 | export * from './slice'; 4 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/navigation/Navigation.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../../utils'; 2 | import { Navigation } from './Navigation'; 3 | 4 | describe('Navigation', () => { 5 | it('renders', () => { 6 | expect(() => render()).not.toThrow(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/navigation/components/Bottom.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../../../utils'; 2 | import { Bottom } from './Bottom'; 3 | 4 | describe('Bottom', () => { 5 | it('renders', () => { 6 | expect(() => render()).not.toThrow(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/navigation/components/Item.test.tsx: -------------------------------------------------------------------------------- 1 | import { List } from '@chakra-ui/react'; 2 | 3 | import { render } from '../../../utils'; 4 | import { Item } from './Item'; 5 | 6 | describe('Item', () => { 7 | it('renders', () => { 8 | expect(() => 9 | render( 10 | 11 | Bar 12 | , 13 | ), 14 | ).not.toThrow(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/navigation/components/NavigationTag.tsx: -------------------------------------------------------------------------------- 1 | import { Tag } from '@chakra-ui/react'; 2 | import { FunctionComponent, ReactNode } from 'react'; 3 | import { useMatch } from 'react-router-dom'; 4 | 5 | type NavigationTagProps = { 6 | path: string; 7 | children: ReactNode; 8 | }; 9 | 10 | export const NavigationTag: FunctionComponent = ({ 11 | children, 12 | path, 13 | }) => { 14 | const active = useMatch(path); 15 | const isActive = Boolean(active); 16 | 17 | return ( 18 | 24 | {children} 25 | 26 | ); 27 | }; 28 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/navigation/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Bottom'; 2 | export * from './Item'; 3 | export * from './ManifestStatusIndicator'; 4 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/navigation/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Navigation'; 2 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/notifications/Notifications.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../../utils'; 2 | import { Notifications } from './Notifications'; 3 | 4 | describe('Notifications', () => { 5 | it('renders', () => { 6 | expect(() => render()).not.toThrow(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/notifications/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Notifications'; 2 | export * from './slice'; 3 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/polling/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sagas'; 2 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/renderer/components/Divider.tsx: -------------------------------------------------------------------------------- 1 | import { Divider as ChakraDivider } from '@chakra-ui/react'; 2 | import { FunctionComponent } from 'react'; 3 | 4 | export type DividerProps = { 5 | id: string; 6 | node: unknown; 7 | }; 8 | 9 | export const Divider: FunctionComponent = ({ id }) => ( 10 | 17 | ); 18 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/renderer/components/Spinner.tsx: -------------------------------------------------------------------------------- 1 | import { Spinner as ChakraSpinner } from '@chakra-ui/react'; 2 | import { FunctionComponent } from 'react'; 3 | 4 | export type SpinnerProps = { 5 | id: string; 6 | node: unknown; 7 | }; 8 | 9 | export const Spinner: FunctionComponent = ({ id }) => ( 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/renderer/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Copyable'; 2 | export * from './Divider'; 3 | export * from './Heading'; 4 | export * from './Panel'; 5 | export * from './Spinner'; 6 | export * from './Text'; 7 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/renderer/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Renderer'; 2 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/simulation/constants.ts: -------------------------------------------------------------------------------- 1 | // TODO: Use something else? 2 | export const JSON_RPC_ENDPOINT = 'https://cloudflare-eth.com/'; 3 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/simulation/index.library.ts: -------------------------------------------------------------------------------- 1 | export * from './constants'; 2 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/simulation/index.ts: -------------------------------------------------------------------------------- 1 | export * from './hooks'; 2 | export * from './sagas'; 3 | export * from './slice'; 4 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/simulation/test/mockExecutionService.ts: -------------------------------------------------------------------------------- 1 | export class MockExecutionService { 2 | terminateAllSnaps() { 3 | // no-op for now 4 | } 5 | 6 | executeSnap() { 7 | // no-op for now 8 | } 9 | 10 | handleRpcRequest() { 11 | return 'foobar'; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/status/StatusIndicator.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '../../utils'; 2 | import { StatusIndicator } from './StatusIndicator'; 3 | 4 | describe('StatusIndicator', () => { 5 | it('renders', () => { 6 | expect(() => render()).not.toThrow(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/features/status/index.ts: -------------------------------------------------------------------------------- 1 | export * from './StatusIndicator'; 2 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useDispatch'; 2 | export * from './useHandler'; 3 | export * from './useSelector'; 4 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/hooks/useDispatch.ts: -------------------------------------------------------------------------------- 1 | import { useDispatch as useReduxDispatch } from 'react-redux'; 2 | 3 | import { Dispatch } from '../store/store'; 4 | 5 | /** 6 | * A hook to access the Redux dispatch function. 7 | * 8 | * This is a wrapper around the `useDispatch` hook from `react-redux`, to 9 | * provide a type-safe `Dispatch` type. 10 | * 11 | * @returns The Redux dispatch function. 12 | */ 13 | export const useDispatch: () => Dispatch = useReduxDispatch; 14 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/hooks/useHandler.tsx: -------------------------------------------------------------------------------- 1 | import { HandlerType } from '@metamask/snaps-utils'; 2 | import { assert } from '@metamask/utils'; 3 | import { useMatch } from 'react-router-dom'; 4 | 5 | type SupportedHandler = 6 | | HandlerType.OnRpcRequest 7 | | HandlerType.OnCronjob 8 | | HandlerType.OnTransaction; 9 | 10 | /** 11 | * Get the handler ID from the current route. 12 | * 13 | * @returns The handler ID from the current route. 14 | */ 15 | export function useHandler(): SupportedHandler { 16 | const match = useMatch('/handler/:handlerId'); 17 | const handlerId = match?.params.handlerId; 18 | 19 | assert(handlerId, '`useHandler` must be used within a `Handler` component.'); 20 | 21 | return handlerId as SupportedHandler; 22 | } 23 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/hooks/useSelector.ts: -------------------------------------------------------------------------------- 1 | import { 2 | TypedUseSelectorHook, 3 | useSelector as useReduxSelector, 4 | } from 'react-redux'; 5 | 6 | import { ApplicationState } from '../store/store'; 7 | 8 | /** 9 | * A hook to access the Redux store's state. 10 | * 11 | * This is a wrapper around the `useSelector` hook from `react-redux`, to 12 | * provide a type-safe `ApplicationState` type. 13 | * 14 | * @returns The Redux store's state. 15 | */ 16 | export const useSelector: TypedUseSelectorHook = 17 | useReduxSelector; 18 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Snaps Simulator 7 | 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './features/index.library'; 2 | export * from './store/index.library'; 3 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/store/index.library.ts: -------------------------------------------------------------------------------- 1 | export type { ApplicationState, Dispatch } from './store'; 2 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/store/index.ts: -------------------------------------------------------------------------------- 1 | export * from './store'; 2 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/store/middleware.ts: -------------------------------------------------------------------------------- 1 | import createSagaMiddleware from 'redux-saga'; 2 | 3 | export const sagaMiddleware = createSagaMiddleware(); 4 | 5 | /** 6 | * A function to run a saga outside of the usual Redux flow. 7 | * 8 | * This is useful for running sagas, and waiting for a result using promises. 9 | * For example: 10 | * 11 | * ```ts 12 | * const result = await runSaga(mySaga, ...args).toPromise(); 13 | * ``` 14 | */ 15 | export const runSaga = sagaMiddleware.run.bind(sagaMiddleware); 16 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/store/sagas.ts: -------------------------------------------------------------------------------- 1 | import { all, fork } from 'redux-saga/effects'; 2 | 3 | import { simulationSaga, rootPollingSaga, manifestSaga } from '../features'; 4 | 5 | /** 6 | * Root saga for the application. 7 | * 8 | * @yields All sagas for the application. 9 | */ 10 | export function* rootSaga() { 11 | // To avoid one saga failing and crashing all sagas, we fork each saga 12 | // individually. 13 | yield all([fork(simulationSaga), fork(rootPollingSaga), fork(manifestSaga)]); 14 | } 15 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/stub.ts: -------------------------------------------------------------------------------- 1 | const stub = 'stub'; 2 | export default stub; 3 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/types.d.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/unambiguous 2 | declare module '*.svg'; 3 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/types/vendor/offscreen.d.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/unambiguous 2 | declare namespace chrome.offscreen { 3 | export type Reason = 4 | | 'TESTING' 5 | | 'AUDIO_PLAYBACK' 6 | | 'IFRAME_SCRIPTING' 7 | | 'DOM_SCRAPING' 8 | | 'BLOBS' 9 | | 'DOM_PARSER' 10 | | 'USER_MEDIA' 11 | | 'DISPLAY_MEDIA' 12 | | 'WEB_RTC' 13 | | 'CLIPBOARD'; 14 | 15 | export type CreateParameters = { 16 | justification: string; 17 | reasons: Reason[]; 18 | url: string; 19 | }; 20 | 21 | export function hasDocument(): Promise; 22 | 23 | export function createDocument( 24 | parameters: CreateParameters, 25 | callback?: () => void, 26 | ): Promise; 27 | 28 | export function closeDocument(callback?: () => void): Promise; 29 | } 30 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/utils/environment.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Whether the current build is a test build, i.e., it was built with the 3 | * `SNAPS_TEST` environment variable set to `true`. 4 | */ 5 | export const IS_TEST_BUILD = 6 | // @ts-expect-error - Webpack replaces the value of SNAPS_TEST with a boolean 7 | // at build time, but TypeScript doesn't know that. 8 | process.env.SNAPS_TEST === true || process.env.SNAPS_TEST === 'true'; 9 | -------------------------------------------------------------------------------- /packages/snaps-simulator/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './environment'; 2 | export * from './render'; 3 | -------------------------------------------------------------------------------- /packages/snaps-simulator/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.build.json", 3 | "compilerOptions": { 4 | "jsx": "react-jsx", 5 | "baseUrl": "./", 6 | "outDir": "./dist/types", 7 | "rootDir": "./", 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true 10 | }, 11 | "include": ["./src", "package.json"], 12 | "exclude": [ 13 | "**/*.test.ts", 14 | "**/*.test.tsx", 15 | "./src/**/test-utils", 16 | "./src/**/__mocks__", 17 | "./src/**/__snapshots__" 18 | ], 19 | "references": [ 20 | { "path": "../rpc-methods/tsconfig.build.json" }, 21 | { "path": "../snaps-controllers/tsconfig.build.json" }, 22 | { "path": "../snaps-utils/tsconfig.build.json" }, 23 | { "path": "../snaps-ui/tsconfig.build.json" } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /packages/snaps-simulator/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "jsx": "react-jsx", 6 | "resolveJsonModule": true 7 | }, 8 | "include": ["./src", "webpack.config.ts", "package.json"], 9 | "references": [ 10 | { "path": "../rpc-methods" }, 11 | { "path": "../snaps-controllers" }, 12 | { "path": "../snaps-utils" }, 13 | { "path": "../snaps-ui" } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/snaps-types/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | ignorePatterns: ['**/*.d.ts'], 5 | 6 | parserOptions: { 7 | tsconfigRootDir: __dirname, 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /packages/snaps-types/README.md: -------------------------------------------------------------------------------- 1 | # @metamask/snaps-types 2 | 3 | TypeScript types used by MetaMask Snaps at runtime. Contains both a global declaration for the global snap provider (`wallet`) and importable types for e.g. the `onRpcRequest` handler function. 4 | -------------------------------------------------------------------------------- /packages/snaps-types/src/global.ts: -------------------------------------------------------------------------------- 1 | import type { MetaMaskInpageProvider } from '@metamask/providers'; 2 | import type { SnapsGlobalObject } from '@metamask/rpc-methods'; 3 | 4 | // Types that should be available globally within a snap. 5 | declare global { 6 | const ethereum: MetaMaskInpageProvider; 7 | const snap: SnapsGlobalObject; 8 | } 9 | -------------------------------------------------------------------------------- /packages/snaps-types/src/index.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/no-unassigned-import 2 | import './global'; 3 | 4 | export * from './types'; 5 | -------------------------------------------------------------------------------- /packages/snaps-types/src/types.ts: -------------------------------------------------------------------------------- 1 | import { StreamProvider } from '@metamask/providers'; 2 | 3 | /** 4 | * The type of `window.ethereum`. 5 | */ 6 | export type Ethereum = StreamProvider; 7 | 8 | // Exported again for convenience. 9 | export type { Json, JsonRpcRequest } from '@metamask/utils'; 10 | export { 11 | DialogType, 12 | NotificationType, 13 | ManageStateOperation, 14 | } from '@metamask/rpc-methods'; 15 | export type { SnapsGlobalObject } from '@metamask/rpc-methods'; 16 | export type { 17 | AccountId, 18 | ChainId, 19 | OnCronjobHandler, 20 | OnRpcRequestHandler, 21 | OnTransactionHandler, 22 | OnTransactionResponse, 23 | } from '@metamask/snaps-utils'; 24 | -------------------------------------------------------------------------------- /packages/snaps-types/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.build.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/types", 6 | "rootDir": "./src" 7 | }, 8 | "include": ["./src"], 9 | "references": [ 10 | { 11 | "path": "../rpc-methods/tsconfig.build.json" 12 | }, 13 | { 14 | "path": "../snaps-utils/tsconfig.build.json" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /packages/snaps-types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.json", 3 | "compilerOptions": { 4 | "baseUrl": "./" 5 | }, 6 | "include": ["./src"], 7 | "references": [ 8 | { 9 | "path": "../rpc-methods" 10 | }, 11 | { 12 | "path": "../snaps-utils" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/snaps-ui/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/snaps-ui/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2022 MetaMask 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /packages/snaps-ui/README.md: -------------------------------------------------------------------------------- 1 | # @metamask/snaps-ui 2 | 3 | A MetaMask Snaps UI library. 4 | 5 | ## Installation 6 | 7 | Use Node.js `16.0.0` or later. We recommend using [nvm](https://github.com/nvm-sh/nvm) for managing Node.js versions. 8 | 9 | Install a dependency in your snap project using `yarn` or `npm`: 10 | 11 | - `npm install @metamask/snaps-ui` 12 | - `yarn add @metamask/snaps-ui` 13 | -------------------------------------------------------------------------------- /packages/snaps-ui/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | coverageThreshold: { 7 | global: { 8 | branches: 100, 9 | functions: 100, 10 | lines: 100, 11 | statements: 100, 12 | }, 13 | }, 14 | }); 15 | -------------------------------------------------------------------------------- /packages/snaps-ui/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './builder'; 2 | export * from './nodes'; 3 | export * from './validation'; 4 | -------------------------------------------------------------------------------- /packages/snaps-ui/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.build.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/types", 6 | "rootDir": "./src" 7 | }, 8 | "include": ["./src"], 9 | "exclude": [ 10 | "**/*.test.ts", 11 | "./src/**/test-utils", 12 | "./src/**/__mocks__", 13 | "./src/**/__snapshots__" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/snaps-ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.json", 3 | "compilerOptions": { 4 | "baseUrl": "./" 5 | }, 6 | "include": ["./src"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/snaps-utils/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/snaps-utils/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | dist 4 | dist-temp 5 | temp 6 | *.log 7 | *.tgz 8 | 9 | public/ 10 | src/__GENERATED__/ 11 | -------------------------------------------------------------------------------- /packages/snaps-utils/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2022 MetaMask 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /packages/snaps-utils/README.md: -------------------------------------------------------------------------------- 1 | # @metamask/snaps-utils 2 | 3 | Shared utility functions used by the other packages. 4 | -------------------------------------------------------------------------------- /packages/snaps-utils/coverage.json: -------------------------------------------------------------------------------- 1 | { 2 | "branches": 94.47, 3 | "functions": 100, 4 | "lines": 98.45, 5 | "statements": 95.35 6 | } 7 | -------------------------------------------------------------------------------- /packages/snaps-utils/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../jest.config.base'); 4 | 5 | delete baseConfig.coverageThreshold; 6 | 7 | module.exports = deepmerge(baseConfig, { 8 | coverageDirectory: './coverage/jest', 9 | coveragePathIgnorePatterns: [ 10 | './src/index.ts', 11 | './src/index.browser.ts', 12 | './src/virtual-file/index.ts', 13 | './src/virtual-file/index.browser.ts', 14 | './src/manifest/index.ts', 15 | './src/manifest/index.browser.ts', 16 | './src/test-utils', 17 | './src/json-schemas', 18 | // Jest currently doesn't collect coverage for child processes. 19 | // https://github.com/facebook/jest/issues/5274 20 | './src/eval-worker.ts', 21 | ], 22 | }); 23 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/__mocks__/fs.ts: -------------------------------------------------------------------------------- 1 | import { fs } from 'memfs'; 2 | 3 | // Note: 'memfs' implements most of the `fs` API, but not all. 4 | export = fs; 5 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/__mocks__/fs/promises.ts: -------------------------------------------------------------------------------- 1 | import { fs } from 'memfs'; 2 | 3 | export = fs.promises; 4 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/array.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if array `a` is equal to array `b`. Note that this does not do a deep 3 | * equality check. It only checks if the arrays are the same length and if each 4 | * element in `a` is equal to (`===`) the corresponding element in `b`. 5 | * 6 | * @param a - The first array to compare. 7 | * @param b - The second array to compare. 8 | * @returns `true` if the arrays are equal, `false` otherwise. 9 | */ 10 | export function isEqual(a: unknown[], b: unknown[]): boolean { 11 | return a.length === b.length && a.every((value, index) => value === b[index]); 12 | } 13 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/caveats.test.ts: -------------------------------------------------------------------------------- 1 | import { SnapCaveatType } from './caveats'; 2 | 3 | describe('Caveat utilities', () => { 4 | it('exports expected caveats', () => { 5 | expect(SnapCaveatType.PermittedDerivationPaths).toBe( 6 | 'permittedDerivationPaths', 7 | ); 8 | 9 | expect(SnapCaveatType.PermittedCoinTypes).toBe('permittedCoinTypes'); 10 | 11 | expect(SnapCaveatType.SnapCronjob).toBe('snapCronjob'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/deep-clone.ts: -------------------------------------------------------------------------------- 1 | import rfdc from 'rfdc'; 2 | 3 | export const deepClone = rfdc({ proto: false, circles: false }); 4 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/entropy.ts: -------------------------------------------------------------------------------- 1 | // 0xd36e6170 - 0x80000000 2 | export const SIP_6_MAGIC_VALUE = `1399742832'` as `${number}'`; 3 | 4 | // `${bytesToNumber(keccak256('Snaps state encryption').slice(0, 4))}'` 5 | export const STATE_ENCRYPTION_MAGIC_VALUE = `572232532'` as `${number}'`; 6 | 7 | export type MagicValue = 8 | | typeof SIP_6_MAGIC_VALUE 9 | | typeof STATE_ENCRYPTION_MAGIC_VALUE; 10 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/enum.test.ts: -------------------------------------------------------------------------------- 1 | import { is } from 'superstruct'; 2 | 3 | import { enumValue } from './enum'; 4 | 5 | describe('enumValue', () => { 6 | it('validates an enum value', () => { 7 | enum Foo { 8 | Bar = 'bar', 9 | Baz = 'baz', 10 | } 11 | 12 | const struct = enumValue(Foo.Bar); 13 | 14 | expect(is('bar', struct)).toBe(true); 15 | expect(is('baz', struct)).toBe(false); 16 | expect(is(Foo.Bar, struct)).toBe(true); 17 | expect(is(Foo.Baz, struct)).toBe(false); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/eval-worker.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // This exists just for testing. 4 | require('./eval-worker.ts'); 5 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/icon.ts: -------------------------------------------------------------------------------- 1 | import { assert } from '@metamask/utils'; 2 | import isSvg from 'is-svg'; 3 | 4 | import { VirtualFile } from './virtual-file'; 5 | 6 | export const SVG_MAX_BYTE_SIZE = 100_000; 7 | export const SVG_MAX_BYTE_SIZE_TEXT = `${Math.floor( 8 | SVG_MAX_BYTE_SIZE / 1000, 9 | )}kb`; 10 | 11 | export const assertIsSnapIcon = (icon: VirtualFile) => { 12 | assert(icon.path.endsWith('.svg'), 'Expected snap icon to end in ".svg".'); 13 | 14 | assert( 15 | Buffer.byteLength(icon.value, 'utf8') <= SVG_MAX_BYTE_SIZE, 16 | `The specified SVG icon exceeds the maximum size of ${SVG_MAX_BYTE_SIZE_TEXT}.`, 17 | ); 18 | 19 | assert(isSvg(icon.toString()), 'Snap icon must be a valid SVG.'); 20 | }; 21 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/iframe.test.browser.ts: -------------------------------------------------------------------------------- 1 | import { createWindow } from './iframe'; 2 | 3 | const IFRAME_URL = `http://localhost:4569`; 4 | 5 | const MOCK_JOB_ID = 'job-id'; 6 | 7 | describe('createWindow', () => { 8 | it('creates an iframe window with the provided job ID as the iframe ID', async () => { 9 | const window = await createWindow(IFRAME_URL, MOCK_JOB_ID); 10 | const iframe = document.getElementById(MOCK_JOB_ID) as HTMLIFrameElement; 11 | 12 | expect(iframe).toBeDefined(); 13 | expect(iframe.contentWindow).toBe(window); 14 | expect(iframe.id).toBe(MOCK_JOB_ID); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/index.browser.ts: -------------------------------------------------------------------------------- 1 | export * from './array'; 2 | export * from './caveats'; 3 | export * from './checksum'; 4 | export * from './cronjob'; 5 | export * from './deep-clone'; 6 | export * from './default-endowments'; 7 | export * from './entropy'; 8 | export * from './enum'; 9 | export * from './handlers'; 10 | export * from './iframe'; 11 | export * from './json'; 12 | export * from './json-rpc'; 13 | export * from './logging'; 14 | export * from './manifest/index.browser'; 15 | export * from './namespace'; 16 | export * from './path'; 17 | export * from './snaps'; 18 | export * from './types'; 19 | export * from './validation'; 20 | export * from './versions'; 21 | export * from './virtual-file/index.browser'; 22 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/index.executionenv.ts: -------------------------------------------------------------------------------- 1 | // Special entrypoint for execution environments for bundle sizing reasons 2 | export * from './handlers'; 3 | export * from './logging'; 4 | export * from './namespace'; 5 | export * from './types'; 6 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/json.test.ts: -------------------------------------------------------------------------------- 1 | import { parseJson } from './json'; 2 | 3 | describe('parseJson', () => { 4 | it('strips __proto__ and constructor', () => { 5 | const input = 6 | '{ "test": { "__proto__": { "foo": "bar" } }, "test2": { "constructor": { "baz": "qux" } } }'; 7 | expect(parseJson(input)).toStrictEqual({ test: {}, test2: {} }); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/json.ts: -------------------------------------------------------------------------------- 1 | import { getSafeJson, Json } from '@metamask/utils'; 2 | 3 | // TODO: Upstream this to @metamask/utils 4 | 5 | /** 6 | * Parse JSON safely. 7 | * 8 | * Does multiple kinds of validation and strips unwanted properties like 9 | * `__proto__` and `constructor`. 10 | * 11 | * @param json - A JSON string to be parsed. 12 | * @returns The parsed JSON object. 13 | * @template Type - The type of the JSON object. The type is not actually 14 | * checked, but it is used to infer the return type. 15 | */ 16 | export function parseJson(json: string) { 17 | return getSafeJson(JSON.parse(json)); 18 | } 19 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/manifest/index.browser.ts: -------------------------------------------------------------------------------- 1 | export * from './validation'; 2 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/manifest/index.ts: -------------------------------------------------------------------------------- 1 | export * from './manifest'; 2 | export * from './validation'; 3 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/path.test.ts: -------------------------------------------------------------------------------- 1 | import { AssertionError } from '@metamask/utils'; 2 | 3 | import { normalizeRelative } from './path'; 4 | 5 | describe('normalizeRelative', () => { 6 | it('throws on absolute paths', () => { 7 | expect(() => normalizeRelative('/foo/bar.js')).toThrow(AssertionError); 8 | }); 9 | 10 | it('throws on URIs', () => { 11 | expect(() => normalizeRelative('http://foo.bar')).toThrow( 12 | 'Path "http://foo.bar" potentially an URI instead of local relative', 13 | ); 14 | }); 15 | 16 | it('removes "./" prefix', () => { 17 | expect(normalizeRelative('./foo/bar.js')).toBe('foo/bar.js'); 18 | }); 19 | 20 | it("does nothing if there's no prefix", () => { 21 | expect(normalizeRelative('foo/bar.js')).toBe('foo/bar.js'); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/path.ts: -------------------------------------------------------------------------------- 1 | import { assert } from '@metamask/utils'; 2 | 3 | /** 4 | * Normalizes relative paths by optionally removing `./` prefix. 5 | * 6 | * @param path - Path to make normalize. 7 | * @returns The same path, with `./` prefix remove. 8 | */ 9 | // TODO(ritave): Include NodeJS path polyfill and use path.normalize as well 10 | export function normalizeRelative(path: string): string { 11 | assert(!path.startsWith('/')); 12 | assert( 13 | path.search(/:|\/\//u) === -1, 14 | `Path "${path}" potentially an URI instead of local relative`, 15 | ); 16 | 17 | if (path.startsWith('./')) { 18 | return path.slice(2); 19 | } 20 | return path; 21 | } 22 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/test-utils/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Shared utils which can be used in tests in any package. These are exported as 3 | * `@metamask/utils/test-utils`, and can be imported from there. They should 4 | * only be used in tests, and should not be used in production code. 5 | */ 6 | 7 | export * from './common'; 8 | export * from './manifest'; 9 | export * from './sleep'; 10 | export * from './snap'; 11 | export * from './spy'; 12 | export * from './stream'; 13 | export * from './controller'; 14 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/test-utils/sleep.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Get a promise that resolves after a given number of milliseconds. 3 | * 4 | * @param ms - The number of milliseconds to sleep. 5 | * @returns A promise that resolves after the given number of milliseconds. 6 | */ 7 | export async function sleep(ms: number): Promise { 8 | return new Promise((resolve) => setTimeout(resolve, ms)); 9 | } 10 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/validation.ts: -------------------------------------------------------------------------------- 1 | import { assertIsSnapIcon } from './icon'; 2 | import { assertIsSnapManifest } from './manifest/validation'; 3 | import { validateSnapShasum } from './snaps'; 4 | import { SnapFiles } from './types'; 5 | 6 | /** 7 | * Validates the files contained in a fetched snap. 8 | * 9 | * @param files - All potentially included files in a fetched snap. 10 | * @throws If any of the files are considered invalid. 11 | */ 12 | export function validateFetchedSnap( 13 | files: Pick, 14 | ): void { 15 | assertIsSnapManifest(files.manifest.result); 16 | validateSnapShasum(files); 17 | 18 | if (files.svgIcon) { 19 | assertIsSnapIcon(files.svgIcon); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/virtual-file/index.browser.ts: -------------------------------------------------------------------------------- 1 | export * from './VirtualFile'; 2 | -------------------------------------------------------------------------------- /packages/snaps-utils/src/virtual-file/index.ts: -------------------------------------------------------------------------------- 1 | export * from './toVirtualFile'; 2 | export * from './VirtualFile'; 3 | -------------------------------------------------------------------------------- /packages/snaps-utils/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.build.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/types", 6 | "rootDir": "./src" 7 | }, 8 | "include": ["./src"], 9 | "exclude": [ 10 | "**/*.test.ts", 11 | "./src/**/test-utils", 12 | "./src/**/__mocks__", 13 | "./src/**/__snapshots__", 14 | "./src/eval-worker.js", 15 | "wdio.config.ts", 16 | "scripts" 17 | ], 18 | "references": [ 19 | { 20 | "path": "../snaps-ui/tsconfig.build.json" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/snaps-utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.json", 3 | "compilerOptions": { 4 | "baseUrl": "./" 5 | }, 6 | "include": ["./src", "wdio.config.ts", "scripts"], 7 | "references": [{ "path": "../snaps-ui" }] 8 | } 9 | -------------------------------------------------------------------------------- /packages/snaps-webpack-plugin/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/snaps-webpack-plugin/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | dist 4 | dist-temp 5 | temp 6 | *.log 7 | *.tgz 8 | 9 | public/ 10 | src/__GENERATED__/ 11 | -------------------------------------------------------------------------------- /packages/snaps-webpack-plugin/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2022 MetaMask 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /packages/snaps-webpack-plugin/jest.config.js: -------------------------------------------------------------------------------- 1 | const deepmerge = require('deepmerge'); 2 | 3 | const baseConfig = require('../../jest.config.base'); 4 | 5 | module.exports = deepmerge(baseConfig, { 6 | coverageThreshold: { 7 | global: { 8 | branches: 100, 9 | functions: 100, 10 | lines: 100, 11 | statements: 100, 12 | }, 13 | }, 14 | }); 15 | -------------------------------------------------------------------------------- /packages/snaps-webpack-plugin/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './plugin'; 2 | export type { Options } from './plugin'; 3 | -------------------------------------------------------------------------------- /packages/snaps-webpack-plugin/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.build.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/types", 6 | "rootDir": "./src" 7 | }, 8 | "include": ["./src"], 9 | "exclude": [ 10 | "**/*.test.ts", 11 | "./src/**/test-utils", 12 | "./src/**/__mocks__", 13 | "./src/**/__snapshots__" 14 | ], 15 | "references": [ 16 | { 17 | "path": "../snaps-utils/tsconfig.build.json" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/snaps-webpack-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.packages.json", 3 | "compilerOptions": { 4 | "baseUrl": "./" 5 | }, 6 | "include": ["./src"], 7 | "references": [ 8 | { 9 | "path": "../snaps-utils" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /scripts/get.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -x 4 | set -e 5 | set -u 6 | set -o pipefail 7 | 8 | KEY="${1}" 9 | OUTPUT="${2}" 10 | 11 | if [[ -z $KEY ]]; then 12 | echo "Error: KEY not specified." 13 | exit 1 14 | fi 15 | 16 | if [[ -z $OUTPUT ]]; then 17 | echo "Error: OUTPUT not specified." 18 | exit 1 19 | fi 20 | 21 | echo "$OUTPUT=$(jq --raw-output "$KEY" package.json)" >> "$GITHUB_OUTPUT" 22 | -------------------------------------------------------------------------------- /tsconfig.packages.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.packages.json", 3 | "compilerOptions": { 4 | "declaration": true, 5 | "emitDeclarationOnly": true, 6 | "inlineSources": true, 7 | "sourceMap": true, 8 | "module": "ES2020" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tsconfig.packages.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "esModuleInterop": true, 5 | "forceConsistentCasingInFileNames": true, 6 | "lib": ["DOM", "ES2020"], 7 | "module": "CommonJS", 8 | "moduleResolution": "node", 9 | "paths": { 10 | "@metamask/*/test-utils": ["../*/src/test-utils"], 11 | "@metamask/*": ["../*/src"] 12 | }, 13 | "resolveJsonModule": true, 14 | "strict": true, 15 | "target": "ES2020", 16 | "useUnknownInCatchVariables": false 17 | } 18 | } 19 | --------------------------------------------------------------------------------