diff --git a/.github/workflows/build-lint-test.yml b/.github/workflows/build-lint-test.yml index 1cf68bffae..267cd3c151 100644 --- a/.github/workflows/build-lint-test.yml +++ b/.github/workflows/build-lint-test.yml @@ -73,39 +73,6 @@ jobs: exit 1 fi - build-simulator: - name: Build "@metamask/snaps-simulator" - runs-on: ubuntu-latest - needs: prepare - steps: - - name: Checkout and setup environment - uses: MetaMask/action-checkout-and-setup@v1 - with: - is-high-risk-environment: false - - name: Restore "@metamask/snaps-execution-environments" build - uses: actions/download-artifact@v4 - with: - name: snaps-execution-environments-build-${{ runner.os }}-22.x-${{ github.sha }} - - name: Cache Webpack vendor - id: cache-webpack-vendor - uses: actions/cache@v4 - with: - path: | - packages/snaps-simulator/vendor - key: webpack-vendor-${{ runner.os }}-${{ hashFiles('yarn.lock') }} - - name: Build Webpack vendor - if: steps.cache-webpack-vendor.outputs.cache-hit != 'true' - run: yarn workspace @metamask/snaps-simulator run build:vendor - - name: Build - run: yarn workspace @metamask/snaps-simulator run build:webpack - - name: Require clean working directory - shell: bash - run: | - if ! git diff --exit-code; then - echo "Working tree dirty at end of job" - exit 1 - fi - build-test-snaps: name: Build "@metamask/test-snaps" runs-on: ubuntu-latest diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cf175c0863..5d0ffb869d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -52,20 +52,6 @@ jobs: secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - publish-staging-simulator: - name: Publish Snaps Simulator to `staging` folder - needs: lint-build-test - if: ${{ github.ref_name == 'main' && github.event_name == 'push' }} - permissions: - contents: write - uses: ./.github/workflows/publish-github-pages.yml - with: - build_script: yarn workspace @metamask/snaps-simulator build - publish_dir: ./packages/snaps-simulator/dist/webpack/main - destination_dir: snaps-simulator/staging - secrets: - PUBLISH_PAGES_TOKEN: ${{ secrets.PUBLISH_PAGES_TOKEN }} - is-release: name: Determine whether this is a release merge commit needs: lint-build-test diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 59c779970d..b30b234918 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -260,56 +260,3 @@ jobs: publish_dir: ./packages/test-snaps/dist secrets: PUBLISH_PAGES_TOKEN: ${{ secrets.PUBLISH_PAGES_TOKEN }} - - is-simulator-release: - name: Determine whether this release updates the simulator - runs-on: ubuntu-latest - needs: publish-release - outputs: - IS_SIMULATOR_RELEASE: ${{ steps.set-output.outputs.IS_SIMULATOR_RELEASE }} - SIMULATOR_VERSION: ${{ steps.set-output.outputs.SIMULATOR_VERSION }} - steps: - - name: Checkout and setup environment - uses: MetaMask/action-checkout-and-setup@v1 - with: - is-high-risk-environment: true - ref: ${{ github.sha }} - fetch-depth: 2 - - name: Check if this is a simulator release - id: is-simulator-release - shell: bash - run: ./scripts/is-release.sh "packages/snaps-simulator/package.json" "${{ github.event.before }}" "IS_SIMULATOR_RELEASE" - - name: Set output - id: set-output - if: steps.is-simulator-release.outputs.IS_SIMULATOR_RELEASE == 'true' - run: | - echo "IS_SIMULATOR_RELEASE=true" >> "$GITHUB_OUTPUT" - echo "SIMULATOR_VERSION=$(jq --raw-output '.version' packages/snaps-simulator/package.json)" >> "$GITHUB_OUTPUT" - - publish-simulator-versioned: - name: Publish Snaps Simulator to `${{ needs.is-simulator-release.outputs.SIMULATOR_VERSION }}` folder - needs: is-simulator-release - if: ${{ needs.is-simulator-release.outputs.IS_SIMULATOR_RELEASE == 'true' }} - permissions: - contents: write - uses: ./.github/workflows/publish-github-pages.yml - with: - build_script: yarn workspace @metamask/snaps-simulator build - publish_dir: ./packages/snaps-simulator/dist/webpack/main - destination_dir: snaps-simulator/${{ needs.is-simulator-release.outputs.SIMULATOR_VERSION }} - secrets: - PUBLISH_PAGES_TOKEN: ${{ secrets.PUBLISH_PAGES_TOKEN }} - - publish-simulator-latest: - name: Publish Snaps Simulator to `latest` folder - needs: is-simulator-release - if: ${{ needs.is-simulator-release.outputs.IS_SIMULATOR_RELEASE == 'true' }} - permissions: - contents: write - uses: ./.github/workflows/publish-github-pages.yml - with: - build_script: yarn workspace @metamask/snaps-simulator build - publish_dir: ./packages/snaps-simulator/dist/webpack/main - destination_dir: snaps-simulator/latest - secrets: - PUBLISH_PAGES_TOKEN: ${{ secrets.PUBLISH_PAGES_TOKEN }} diff --git a/.prettierignore b/.prettierignore index c4d49a767a..624a11dcec 100644 --- a/.prettierignore +++ b/.prettierignore @@ -77,4 +77,3 @@ typings/ packages/examples/examples/webpack/index.html packages/snaps-execution-environments/lavamoat/**/*.json packages/snaps-jest/public -packages/snaps-simulator/vendor diff --git a/eslint.config.mjs b/eslint.config.mjs index 0560a972c7..2a22879db9 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -325,8 +325,6 @@ const config = createConfig([ 'packages/snaps-controllers/src/services/iframe/**/*', 'packages/snaps-controllers/src/services/webworker/**/*', 'packages/snaps-execution-environments/src/**/*', - 'packages/snaps-simulator/src/**/*', - 'packages/snaps-simulator/jest.setup.js', 'packages/test-snaps/src/**/*', '**/*.test.browser.ts', ], diff --git a/packages/snaps-controllers/.depcheckrc.json b/packages/snaps-controllers/.depcheckrc.json index 9602552585..3b2defb555 100644 --- a/packages/snaps-controllers/.depcheckrc.json +++ b/packages/snaps-controllers/.depcheckrc.json @@ -5,6 +5,7 @@ "@lavamoat/preinstall-always-fail", "@metamask/auto-changelog", "@metamask/eslint-*", + "@testing-library/dom", "@types/*", "@typescript-eslint/*", "@vitest/coverage-istanbul", diff --git a/packages/snaps-controllers/package.json b/packages/snaps-controllers/package.json index f57294203a..094f0b914a 100644 --- a/packages/snaps-controllers/package.json +++ b/packages/snaps-controllers/package.json @@ -117,6 +117,7 @@ "@noble/hashes": "^1.7.1", "@swc/core": "1.3.78", "@swc/jest": "^0.2.26", + "@testing-library/dom": "^10.4.0", "@ts-bridge/cli": "^0.6.1", "@types/chrome": "^0.0.237", "@types/concat-stream": "^2.0.0", diff --git a/packages/snaps-execution-environments/.depcheckrc.json b/packages/snaps-execution-environments/.depcheckrc.json index c08bf9937e..9935f838e5 100644 --- a/packages/snaps-execution-environments/.depcheckrc.json +++ b/packages/snaps-execution-environments/.depcheckrc.json @@ -5,6 +5,7 @@ "@lavamoat/preinstall-always-fail", "@metamask/auto-changelog", "@metamask/eslint-*", + "@testing-library/dom", "@types/*", "@typescript-eslint/*", "@vitest/coverage-v8", diff --git a/packages/snaps-execution-environments/lavamoat/build-system/policy.json b/packages/snaps-execution-environments/lavamoat/build-system/policy.json index 79e18a93ae..3bd125b594 100644 --- a/packages/snaps-execution-environments/lavamoat/build-system/policy.json +++ b/packages/snaps-execution-environments/lavamoat/build-system/policy.json @@ -768,7 +768,7 @@ "util.inherits": true }, "packages": { - "@vitest/browser>@testing-library/user-event>@testing-library/dom>@babel/runtime": true + "@testing-library/dom>@babel/runtime": true } }, "@babel/preset-env>@babel/plugin-transform-reserved-words": { @@ -1322,11 +1322,11 @@ "setImmediate": true }, "packages": { - "browserify>duplexer2>readable-stream>isarray": true, "browserify>duplexer2>readable-stream>safe-buffer": true, "browserify>duplexer2>readable-stream>string_decoder": true, "browserify>inherits": true, "browserify>readable-stream>core-util-is": true, + "browserify>readable-stream>isarray": true, "browserify>readable-stream>process-nextick-args": true, "readable-stream>util-deprecate": true } @@ -1501,10 +1501,10 @@ }, "packages": { "browserify>inherits": true, - "browserify>labeled-stream-splicer>stream-splicer>readable-stream>isarray": true, "browserify>labeled-stream-splicer>stream-splicer>readable-stream>safe-buffer": true, "browserify>labeled-stream-splicer>stream-splicer>readable-stream>string_decoder": true, "browserify>readable-stream>core-util-is": true, + "browserify>readable-stream>isarray": true, "browserify>readable-stream>process-nextick-args": true, "readable-stream>util-deprecate": true } @@ -1586,10 +1586,10 @@ }, "packages": { "browserify>inherits": true, - "browserify>module-deps>readable-stream>isarray": true, "browserify>module-deps>readable-stream>safe-buffer": true, "browserify>module-deps>readable-stream>string_decoder": true, "browserify>readable-stream>core-util-is": true, + "browserify>readable-stream>isarray": true, "browserify>readable-stream>process-nextick-args": true, "readable-stream>util-deprecate": true } @@ -1626,10 +1626,10 @@ }, "packages": { "browserify>inherits": true, - "browserify>module-deps>stream-combiner2>readable-stream>isarray": true, "browserify>module-deps>stream-combiner2>readable-stream>safe-buffer": true, "browserify>module-deps>stream-combiner2>readable-stream>string_decoder": true, "browserify>readable-stream>core-util-is": true, + "browserify>readable-stream>isarray": true, "browserify>readable-stream>process-nextick-args": true, "readable-stream>util-deprecate": true } @@ -1686,10 +1686,10 @@ }, "packages": { "browserify>inherits": true, - "browserify>read-only-stream>readable-stream>isarray": true, "browserify>read-only-stream>readable-stream>safe-buffer": true, "browserify>read-only-stream>readable-stream>string_decoder": true, "browserify>readable-stream>core-util-is": true, + "browserify>readable-stream>isarray": true, "browserify>readable-stream>process-nextick-args": true, "readable-stream>util-deprecate": true } @@ -1815,8 +1815,8 @@ "packages": { "browserify>inherits": true, "browserify>readable-stream>core-util-is": true, + "browserify>readable-stream>isarray": true, "browserify>readable-stream>process-nextick-args": true, - "browserify>through2>readable-stream>isarray": true, "browserify>through2>readable-stream>safe-buffer": true, "browserify>through2>readable-stream>string_decoder": true, "readable-stream>util-deprecate": true diff --git a/packages/snaps-execution-environments/package.json b/packages/snaps-execution-environments/package.json index 8a80c14b85..3efc522561 100644 --- a/packages/snaps-execution-environments/package.json +++ b/packages/snaps-execution-environments/package.json @@ -89,6 +89,7 @@ "@metamask/auto-changelog": "^5.0.1", "@swc/core": "1.3.78", "@swc/jest": "^0.2.26", + "@testing-library/dom": "^10.4.0", "@ts-bridge/cli": "^0.6.1", "@types/express": "^4.17.17", "@types/jest": "^27.5.1", diff --git a/packages/snaps-simulator/.depcheckrc.json b/packages/snaps-simulator/.depcheckrc.json deleted file mode 100644 index a00f357582..0000000000 --- a/packages/snaps-simulator/.depcheckrc.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "ignore-patterns": ["dist", "coverage"], - "ignores": [ - "@lavamoat/allow-scripts", - "@lavamoat/preinstall-always-fail", - "@metamask/auto-changelog", - "@metamask/eslint-*", - "@swc/core", - "@types/*", - "@typescript-eslint/*", - "assert", - "css-loader", - "eslint-config-*", - "eslint-plugin-*", - "jest-silent-reporter", - "prettier-plugin-packagejson", - "process", - "style-loader", - "swc-loader", - "ts-node", - "typedoc", - "typescript", - "webpack-cli" - ] -} diff --git a/packages/snaps-simulator/.gitignore b/packages/snaps-simulator/.gitignore deleted file mode 100644 index bbc69bc5f8..0000000000 --- a/packages/snaps-simulator/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# Webpack vendor -vendor diff --git a/packages/snaps-simulator/.swcrc b/packages/snaps-simulator/.swcrc deleted file mode 100644 index 85936b5b2d..0000000000 --- a/packages/snaps-simulator/.swcrc +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/swcrc", - "jsc": { - "parser": { - "syntax": "typescript", - "tsx": true - }, - "transform": { - "react": { - "runtime": "automatic" - } - } - } -} diff --git a/packages/snaps-simulator/CHANGELOG.md b/packages/snaps-simulator/CHANGELOG.md deleted file mode 100644 index 066716fe2e..0000000000 --- a/packages/snaps-simulator/CHANGELOG.md +++ /dev/null @@ -1,142 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [Unreleased] - -## [2.5.0] - -### Added - -- Support JSX and Interactive UI in simulator ([#2409](https://github.com/MetaMask/snaps/pull/2409), [#2363](https://github.com/MetaMask/snaps/pull/2363)) -- Add `snap_getPreferences` ([#2607](https://github.com/MetaMask/snaps/pull/2607)) -- Add support for BIP-32-Ed25519 / CIP-3 key derivation ([#2408](https://github.com/MetaMask/snaps/pull/2408)) - -### Changed - -- Refactor encryption to enable caching ([#2316](https://github.com/MetaMask/snaps/pull/2316)) -- Replace `superstruct` with ESM-compatible fork `@metamask/superstruct` ([#2445](https://github.com/MetaMask/snaps/pull/2445)) - -## [2.4.3] - -### Changed - -- Bump several MetaMask dependencies ([#1999](https://github.com/MetaMask/snaps/pull/1999), [#2065](https://github.com/MetaMask/snaps/pull/2065), [#2064](https://github.com/MetaMask/snaps/pull/2064), [#2069](https://github.com/MetaMask/snaps/pull/2069), [#2054](https://github.com/MetaMask/snaps/pull/2054), [#2086](https://github.com/MetaMask/snaps/pull/2086), [#2100](https://github.com/MetaMask/snaps/pull/2100)) - -## [2.4.2] - -### Changed - -- Bump several MetaMask dependencies ([#1989](https://github.com/MetaMask/snaps/pull/1989)) - -## [2.4.1] - -### Changed - -- Bump several MetaMask dependencies ([#1964](https://github.com/MetaMask/snaps/pull/1964)) - -## [2.4.0] - -### Changed - -- Use `SubtleCrypto` for checksum calculation if available ([#1953](https://github.com/MetaMask/snaps/pull/1953)) - - This reduces the time of the checksum calculation by up to 95% in some - environments. -- Use `@metamask/snaps-sdk` package ([#1930](https://github.com/MetaMask/snaps/pull/1930), - [#1949](https://github.com/MetaMask/snaps/pull/1949), [#1954](https://github.com/MetaMask/snaps/pull/1954)) - - This package replaces the `@metamask/snaps-types` and - - `@metamask/snaps-ui` packages. -- Bump `@metamask/eth-json-rpc-middleware` from `12.0.0` to `12.0.1` ([#1935](https://github.com/MetaMask/snaps/pull/1935)) - -## [2.3.0] - -### Added - -- Add manifest localization functionality ([#1889](https://github.com/MetaMask/snaps/pull/1889)) -- Add support for unencrypted storage using `snap_manageState` ([#1902](https://github.com/MetaMask/snaps/pull/1902)) - -## [2.2.0] - -### Added - -- Add support for links in custom UI ([#1814](https://github.com/MetaMask/snaps/pull/1814)) - -## [2.1.0] - -### Added - -- Add support for the static file API ([#1836](https://github.com/MetaMask/snaps/pull/1836)) - -### Changed - -- Improve error handling ([#1841](https://github.com/MetaMask/snaps/pull/1841)) - - Errors shown in the simulator now more accurately reflect the error thrown by the Snap. - -## [2.0.0] - -### Added - -- Add image component ([#1783](https://github.com/MetaMask/snaps/pull/1783)) - -### Changed - -- **BREAKING:** Bump minimum Node.js version to `^18.16.0` ([#1741](https://github.com/MetaMask/snaps/pull/1741)) - -## [1.0.0] - -### Changed - -- Initial stable release from main branch ([#1757](https://github.com/MetaMask/snaps/pull/1757)) - -## [0.38.1-flask.1] - -### Added - -- Add basic support for account RPC methods in snaps simulator ([#1710](https://github.com/MetaMask/snaps/pull/1710)) - -### Changed - -- Remove `pump` ([#1730](https://github.com/MetaMask/snaps/pull/1730)) -- Bump `metamask/utils` and `metamask/snaps-registry` ([#1738](https://github.com/MetaMask/snaps/pull/1738), [#1694](https://github.com/MetaMask/snaps/pull/1694)) -- Bump @metamask/eth-json-rpc-middleware from 11.0.1 to 11.0.2 ([#1735](https://github.com/MetaMask/snaps/pull/1735)) - -### Fixed - -- Fix error when using single quotes in UI builder ([#1709](https://github.com/MetaMask/snaps/pull/1709)) -- Fix fallback icon in snaps simulator ([#1726](https://github.com/MetaMask/snaps/pull/1726)) - -## [0.38.0-flask.1] - -### Added - -- Add support for `snap_getLocale` JSON-RPC method ([#1684](https://github.com/MetaMask/snaps/pull/1684)) - -### Fixed - -- Remove unused dependencies ([#1680](https://github.com/MetaMask/snaps/pull/1680)) - -## [0.37.2-flask.1] - -### Changed - -- Release package independently ([#1600](https://github.com/MetaMask/snaps/pull/1600)) - - The version of the package no longer needs to match the version of all other - MetaMask Snaps packages. - -[Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-simulator@2.5.0...HEAD -[2.5.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-simulator@2.4.3...@metamask/snaps-simulator@2.5.0 -[2.4.3]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-simulator@2.4.2...@metamask/snaps-simulator@2.4.3 -[2.4.2]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-simulator@2.4.1...@metamask/snaps-simulator@2.4.2 -[2.4.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-simulator@2.4.0...@metamask/snaps-simulator@2.4.1 -[2.4.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-simulator@2.3.0...@metamask/snaps-simulator@2.4.0 -[2.3.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-simulator@2.2.0...@metamask/snaps-simulator@2.3.0 -[2.2.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-simulator@2.1.0...@metamask/snaps-simulator@2.2.0 -[2.1.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-simulator@2.0.0...@metamask/snaps-simulator@2.1.0 -[2.0.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-simulator@1.0.0...@metamask/snaps-simulator@2.0.0 -[1.0.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-simulator@0.38.1-flask.1...@metamask/snaps-simulator@1.0.0 -[0.38.1-flask.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-simulator@0.38.0-flask.1...@metamask/snaps-simulator@0.38.1-flask.1 -[0.38.0-flask.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-simulator@0.37.2-flask.1...@metamask/snaps-simulator@0.38.0-flask.1 -[0.37.2-flask.1]: https://github.com/MetaMask/snaps/releases/tag/@metamask/snaps-simulator@0.37.2-flask.1 diff --git a/packages/snaps-simulator/LICENSE b/packages/snaps-simulator/LICENSE deleted file mode 100644 index b703d6a4a2..0000000000 --- a/packages/snaps-simulator/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -MIT License - -Copyright (c) 2023 MetaMask - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE diff --git a/packages/snaps-simulator/README.md b/packages/snaps-simulator/README.md deleted file mode 100644 index a6b60c2d2a..0000000000 --- a/packages/snaps-simulator/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Snaps Simulator - -A simulator for MetaMask Snaps, to be used for testing and development. The -latest version can be found [here](https://metamask.github.io/snaps/snaps-simulator/latest/). - -## Contributing - -### Setup - -- Install [Node.js](https://nodejs.org) version 16 - - If you are using [nvm](https://github.com/creationix/nvm#installation) (recommended) running `nvm use` will automatically choose the right node version for you. -- Install [Yarn v3](https://yarnpkg.com/getting-started/install) -- Run `yarn install` to install dependencies and run any required post-install scripts - -### Building - -Run `yarn build` to build the project. The built files will be placed in the `dist` directory. - -Run `yarn start` to start a development server. The server will automatically rebuild the project when changes are made. - -### Testing and Linting - -Run `yarn test` to run the tests once. To run tests on file changes, run `yarn test:watch`. - -Run `yarn lint` to run the linter, or run `yarn lint:fix` to run the linter and fix any automatically fixable issues. diff --git a/packages/snaps-simulator/babel.config.js b/packages/snaps-simulator/babel.config.js deleted file mode 100644 index f037a1a2a1..0000000000 --- a/packages/snaps-simulator/babel.config.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = { - presets: [ - [ - '@babel/preset-env', - { - targets: { - node: 'current', - }, - }, - ], - ], -}; diff --git a/packages/snaps-simulator/jest.config.js b/packages/snaps-simulator/jest.config.js deleted file mode 100644 index 52d7602a27..0000000000 --- a/packages/snaps-simulator/jest.config.js +++ /dev/null @@ -1,48 +0,0 @@ -const deepmerge = require('deepmerge'); - -const baseConfig = require('../../jest.config.base'); - -delete baseConfig.transform; - -module.exports = deepmerge(baseConfig, { - coverageThreshold: { - global: { - branches: 54.33, - functions: 60.32, - lines: 80.47, - statements: 80.77, - }, - }, - setupFiles: ['./jest.setup.js'], - testEnvironment: './jest.environment.js', - moduleNameMapper: { - // Mocks out all these file formats when tests are run - '\\.(css|less|scss|sass|svg)$': '/src/assets/file-mock.ts', - }, - transformIgnorePatterns: [ - 'node_modules/(?!(monaco-editor|react-monaco-editor|react-dnd|dnd-core|@react-dnd/*|@minoru/react-dnd-treeview|nanoid))', - ], - - // A map from regular expressions to paths to transformers - transform: { - '^.+\\.(t|j)sx?$': [ - '@swc/jest', - { - jsc: { - target: 'es2022', - parser: { - syntax: 'typescript', - tsx: true, - }, - transform: { - react: { - runtime: 'automatic', - useBuiltins: true, - }, - }, - }, - sourceMaps: false, - }, - ], - }, -}); diff --git a/packages/snaps-simulator/jest.environment.js b/packages/snaps-simulator/jest.environment.js deleted file mode 100644 index de208e70d8..0000000000 --- a/packages/snaps-simulator/jest.environment.js +++ /dev/null @@ -1,18 +0,0 @@ -/* eslint-disable */ -const { TestEnvironment } = require('jest-environment-jsdom'); - -// Custom test environment copied from https://github.com/jsdom/jsdom/issues/2524 -// in order to add TextEncoder to jsdom. TextEncoder is expected by jose. - -module.exports = class CustomTestEnvironment extends TestEnvironment { - async setup() { - await super.setup(); - if (typeof this.global.TextEncoder === 'undefined') { - const { TextEncoder, TextDecoder } = require('util'); - this.global.TextEncoder = TextEncoder; - this.global.TextDecoder = TextDecoder; - this.global.ArrayBuffer = ArrayBuffer; - this.global.Uint8Array = Uint8Array; - } - } -}; diff --git a/packages/snaps-simulator/jest.setup.js b/packages/snaps-simulator/jest.setup.js deleted file mode 100644 index 528e0cd03b..0000000000 --- a/packages/snaps-simulator/jest.setup.js +++ /dev/null @@ -1,14 +0,0 @@ -/* eslint-disable no-undef */ -Object.defineProperty(window, 'matchMedia', { - writable: true, - value: (query) => ({ - matches: false, - media: query, - onchange: null, - addListener: jest.fn(), // deprecated - removeListener: jest.fn(), // deprecated - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - dispatchEvent: jest.fn(), - }), -}); diff --git a/packages/snaps-simulator/package.json b/packages/snaps-simulator/package.json deleted file mode 100644 index 8947e1b900..0000000000 --- a/packages/snaps-simulator/package.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "name": "@metamask/snaps-simulator", - "version": "2.5.0", - "private": true, - "description": "A simulator for MetaMask Snaps, to be used for testing and development", - "keywords": [ - "MetaMask", - "Snaps", - "Ethereum" - ], - "homepage": "https://github.com/MetaMask/snaps/tree/main/packages/snaps-simulator#readme", - "bugs": { - "url": "https://github.com/MetaMask/snaps/issues" - }, - "repository": { - "type": "git", - "url": "https://github.com/MetaMask/snaps.git" - }, - "license": "MIT", - "sideEffects": false, - "files": [], - "scripts": { - "build": "yarn build:vendor && yarn build:webpack", - "build:vendor": "webpack --config-name vendor --mode production --progress", - "build:webpack": "yarn webpack --config-name main --config-name test --mode production --progress", - "changelog:update": "../../scripts/update-changelog.sh @metamask/snaps-simulator", - "changelog:validate": "../../scripts/validate-changelog.sh @metamask/snaps-simulator", - "lint": "yarn lint:eslint && yarn lint:misc --check && yarn changelog:validate && yarn lint:dependencies", - "lint:ci": "yarn lint", - "lint:dependencies": "depcheck", - "lint:eslint": "eslint . --cache", - "lint:fix": "yarn lint:eslint --fix && yarn lint:constraints --fix && yarn lint:misc --write && yarn changelog:validate", - "lint:misc": "prettier --no-error-on-unmatched-pattern --log-level warn \"**/*.json\" \"**/*.md\" \"**/*.html\" \"!CHANGELOG.md\" --ignore-path ../../.gitignore", - "since-latest-release": "../../scripts/since-latest-release.sh", - "start": "webpack serve --config-name main --mode development", - "start:e2e": "webpack serve --config-name test --mode development", - "test": "jest --reporters=jest-silent-reporter", - "test:clean": "jest --clearCache", - "test:post": "jest-it-up", - "test:verbose": "jest --verbose", - "test:watch": "jest --watch" - }, - "dependencies": { - "@chakra-ui/anatomy": "^2.1.1", - "@chakra-ui/react": "^2.6.1", - "@emotion/react": "^11.10.8", - "@emotion/styled": "^11.10.8", - "@ethersproject/units": "^5.7.0", - "@metamask/base-controller": "^8.0.0", - "@metamask/eth-json-rpc-middleware": "^16.0.1", - "@metamask/json-rpc-engine": "^10.0.2", - "@metamask/json-rpc-middleware-stream": "^8.0.7", - "@metamask/key-tree": "^10.1.1", - "@metamask/permission-controller": "^11.0.6", - "@metamask/snaps-controllers": "workspace:^", - "@metamask/snaps-execution-environments": "workspace:^", - "@metamask/snaps-rpc-methods": "workspace:^", - "@metamask/snaps-sdk": "workspace:^", - "@metamask/snaps-utils": "workspace:^", - "@metamask/superstruct": "^3.2.1", - "@metamask/utils": "^11.2.0", - "@minoru/react-dnd-treeview": "^3.4.4", - "@noble/hashes": "^1.7.1", - "@reduxjs/toolkit": "^1.9.5", - "date-fns": "^2.30.0", - "fast-deep-equal": "^3.1.3", - "framer-motion": "^10.12.8", - "he": "^1.2.0", - "lodash.debounce": "^4.0.8", - "lodash.memoize": "^4.1.2", - "lodash.throttle": "^4.1.1", - "monaco-editor": "^0.38.0", - "prettier-2": "npm:prettier@^2.8.8", - "react": "^18.2.0", - "react-dnd": "^16.0.1", - "react-dom": "^18.2.0", - "react-hook-form": "^7.43.9", - "react-monaco-editor": "^0.52.0", - "react-redux": "^8.0.5", - "react-router-dom": "^6.11.1", - "redux": "^4.2.1", - "redux-saga": "^1.2.3" - }, - "devDependencies": { - "@metamask/auto-changelog": "^5.0.1", - "@pmmmwh/react-refresh-webpack-plugin": "^0.5.10", - "@redux-saga/is": "^1.1.3", - "@redux-saga/symbols": "^1.1.3", - "@swc/core": "1.3.78", - "@testing-library/react": "^14.0.0", - "@types/express": "^4.17.17", - "@types/he": "^1.2.3", - "@types/jest": "^27.5.1", - "@types/lodash.debounce": "^4.0.9", - "@types/lodash.memoize": "^4.1.9", - "@types/lodash.throttle": "^4.1.9", - "@types/node": "18.14.2", - "@types/react": "^18.2.5", - "@types/react-dom": "^18.2.3", - "@types/webpack-env": "^1.18.1", - "assert": "^2.0.0", - "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.7.3", - "deepmerge": "^4.2.2", - "depcheck": "^1.4.7", - "eslint": "^9.11.0", - "express": "^4.21.2", - "favicons": "^7.1.2", - "favicons-webpack-plugin": "^6.0.0", - "html-webpack-plugin": "^5.5.0", - "jest": "^29.0.2", - "jest-environment-jsdom": "^29.5.0", - "jest-fetch-mock": "^3.0.3", - "jest-it-up": "^2.0.0", - "jest-silent-reporter": "^0.6.0", - "monaco-editor-webpack-plugin": "^7.0.1", - "prettier": "^3.3.3", - "process": "^0.11.10", - "react-refresh": "^0.14.0", - "readable-stream": "^3.6.2", - "redux-saga-test-plan": "^4.0.6", - "stream-browserify": "^3.0.0", - "style-loader": "^3.3.2", - "swc-loader": "^0.2.3", - "terser-webpack-plugin": "^5.3.9", - "ts-node": "^10.9.1", - "tsconfig-paths-webpack-plugin": "^4.0.1", - "typescript": "~5.3.3", - "webpack": "^5.97.1", - "webpack-cli": "^5.1.4", - "webpack-dev-server": "^4.15.1", - "webpack-merge": "^5.9.0" - }, - "engines": { - "node": "^18.16 || >=20" - } -} diff --git a/packages/snaps-simulator/src/App.test.tsx b/packages/snaps-simulator/src/App.test.tsx deleted file mode 100644 index be4d4c4b03..0000000000 --- a/packages/snaps-simulator/src/App.test.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { render } from '@testing-library/react'; -import fetchMock from 'jest-fetch-mock'; - -import { App } from './App'; -import { Root } from './components'; -import { createStore } from './store'; - -describe('App', () => { - it('renders', () => { - // This polyfills Request which seems to be missing in the Jest testing environment. - fetchMock.enableMocks(); - expect(() => - render( - - - , - ), - ).not.toThrow(); - }); -}); diff --git a/packages/snaps-simulator/src/App.tsx b/packages/snaps-simulator/src/App.tsx deleted file mode 100644 index e340b9a35b..0000000000 --- a/packages/snaps-simulator/src/App.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import type { FunctionComponent } from 'react'; -import { useEffect } from 'react'; -import { RouterProvider } from 'react-router-dom'; - -import { setSnapId } from './features'; -import { useDispatch } from './hooks'; -import { router } from './routes'; - -export const App: FunctionComponent = () => { - const dispatch = useDispatch(); - useEffect(() => { - // Dispatch to start polling the default URL - dispatch(setSnapId('local:http://localhost:8080')); - }, [dispatch]); - return ; -}; diff --git a/packages/snaps-simulator/src/api.ts b/packages/snaps-simulator/src/api.ts deleted file mode 100644 index 2db65b9b47..0000000000 --- a/packages/snaps-simulator/src/api.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { assert } from '@metamask/utils'; -import type { Store } from 'redux'; - -import type { Notification } from './features'; -import type { ApplicationState } from './store'; -import { IS_TEST_BUILD } from './utils'; - -declare global { - // eslint-disable-next-line @typescript-eslint/consistent-type-definitions - interface Window { - // eslint-disable-next-line @typescript-eslint/naming-convention - __SIMULATOR_API__: { - dispatch: Store['dispatch']; - subscribe: Store['subscribe']; - getState: () => ApplicationState; - getRequestId: () => string | undefined; - getNotifications: (requestId: string) => Notification[]; - }; - } -} - -/** - * Sets the window API. This is useful for automated testing. - * - * @param store - The store. - */ -export function setWindowApi(store: Store) { - assert(IS_TEST_BUILD, 'This function should only be called in a test build.'); - - window.__SIMULATOR_API__ = { - dispatch: store.dispatch, - subscribe: store.subscribe.bind(store), - getState: () => store.getState(), - getRequestId: () => store.getState().simulation.requestId, - getNotifications: (requestId: string) => { - const state = store.getState(); - return state.notifications.allNotifications.filter( - (notification) => notification.id === requestId, - ); - }, - }; -} diff --git a/packages/snaps-simulator/src/assets/favicon.svg b/packages/snaps-simulator/src/assets/favicon.svg deleted file mode 100644 index 6bd1939d52..0000000000 --- a/packages/snaps-simulator/src/assets/favicon.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/packages/snaps-simulator/src/assets/file-mock.ts b/packages/snaps-simulator/src/assets/file-mock.ts deleted file mode 100644 index 9559a6e43f..0000000000 --- a/packages/snaps-simulator/src/assets/file-mock.ts +++ /dev/null @@ -1,2 +0,0 @@ -const fileMock = 'test-file-stub'; -export default fileMock; diff --git a/packages/snaps-simulator/src/assets/fonts/EuclidCircularB-Bold.woff2 b/packages/snaps-simulator/src/assets/fonts/EuclidCircularB-Bold.woff2 deleted file mode 100644 index 971fa63644..0000000000 Binary files a/packages/snaps-simulator/src/assets/fonts/EuclidCircularB-Bold.woff2 and /dev/null differ diff --git a/packages/snaps-simulator/src/assets/fonts/EuclidCircularB-Regular.woff2 b/packages/snaps-simulator/src/assets/fonts/EuclidCircularB-Regular.woff2 deleted file mode 100644 index 82b6413932..0000000000 Binary files a/packages/snaps-simulator/src/assets/fonts/EuclidCircularB-Regular.woff2 and /dev/null differ diff --git a/packages/snaps-simulator/src/assets/fonts/IBMPlexMono-Regular.woff2 b/packages/snaps-simulator/src/assets/fonts/IBMPlexMono-Regular.woff2 deleted file mode 100644 index 89713fa9ae..0000000000 Binary files a/packages/snaps-simulator/src/assets/fonts/IBMPlexMono-Regular.woff2 and /dev/null differ diff --git a/packages/snaps-simulator/src/assets/fonts/fonts.css b/packages/snaps-simulator/src/assets/fonts/fonts.css deleted file mode 100644 index 2274be0160..0000000000 --- a/packages/snaps-simulator/src/assets/fonts/fonts.css +++ /dev/null @@ -1,20 +0,0 @@ -@font-face { - font-family: 'Euclid Circular B'; - font-style: normal; - font-weight: 400; - src: url('./EuclidCircularB-Regular.woff2') format('woff2'); -} - -@font-face { - font-family: 'Euclid Circular B'; - font-style: normal; - font-weight: 700; - src: url('./EuclidCircularB-Bold.woff2') format('woff2'); -} - -@font-face { - font-family: 'IBM Plex Mono'; - font-style: normal; - font-weight: 400; - src: url('./IBMPlexMono-Regular.woff2') format('woff2'); -} diff --git a/packages/snaps-simulator/src/assets/icons/alert.svg b/packages/snaps-simulator/src/assets/icons/alert.svg deleted file mode 100644 index 8a23bd8cfe..0000000000 --- a/packages/snaps-simulator/src/assets/icons/alert.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/packages/snaps-simulator/src/assets/icons/arrow-down.svg b/packages/snaps-simulator/src/assets/icons/arrow-down.svg deleted file mode 100644 index d5f2430e0d..0000000000 --- a/packages/snaps-simulator/src/assets/icons/arrow-down.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/arrow-right.svg b/packages/snaps-simulator/src/assets/icons/arrow-right.svg deleted file mode 100644 index 75475622a1..0000000000 --- a/packages/snaps-simulator/src/assets/icons/arrow-right.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/arrow-top-right.svg b/packages/snaps-simulator/src/assets/icons/arrow-top-right.svg deleted file mode 100644 index 217f5274c4..0000000000 --- a/packages/snaps-simulator/src/assets/icons/arrow-top-right.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/button.svg b/packages/snaps-simulator/src/assets/icons/button.svg deleted file mode 100644 index eb51f581d5..0000000000 --- a/packages/snaps-simulator/src/assets/icons/button.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/computer.svg b/packages/snaps-simulator/src/assets/icons/computer.svg deleted file mode 100644 index addd20f964..0000000000 --- a/packages/snaps-simulator/src/assets/icons/computer.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/configuration-dark.svg b/packages/snaps-simulator/src/assets/icons/configuration-dark.svg deleted file mode 100644 index e133ca8ca9..0000000000 --- a/packages/snaps-simulator/src/assets/icons/configuration-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/configuration.svg b/packages/snaps-simulator/src/assets/icons/configuration.svg deleted file mode 100644 index 323d176b53..0000000000 --- a/packages/snaps-simulator/src/assets/icons/configuration.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/copied.svg b/packages/snaps-simulator/src/assets/icons/copied.svg deleted file mode 100644 index 826e834bc6..0000000000 --- a/packages/snaps-simulator/src/assets/icons/copied.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/snaps-simulator/src/assets/icons/copy.svg b/packages/snaps-simulator/src/assets/icons/copy.svg deleted file mode 100644 index 2a99540e74..0000000000 --- a/packages/snaps-simulator/src/assets/icons/copy.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/snaps-simulator/src/assets/icons/copyable.svg b/packages/snaps-simulator/src/assets/icons/copyable.svg deleted file mode 100644 index 77480c787c..0000000000 --- a/packages/snaps-simulator/src/assets/icons/copyable.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/snaps-simulator/src/assets/icons/cronjob.svg b/packages/snaps-simulator/src/assets/icons/cronjob.svg deleted file mode 100644 index 590c6ffa42..0000000000 --- a/packages/snaps-simulator/src/assets/icons/cronjob.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/snaps-simulator/src/assets/icons/cross-dark.svg b/packages/snaps-simulator/src/assets/icons/cross-dark.svg deleted file mode 100644 index 7463bd8694..0000000000 --- a/packages/snaps-simulator/src/assets/icons/cross-dark.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/snaps-simulator/src/assets/icons/cross.svg b/packages/snaps-simulator/src/assets/icons/cross.svg deleted file mode 100644 index 77c74c1cff..0000000000 --- a/packages/snaps-simulator/src/assets/icons/cross.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/snaps-simulator/src/assets/icons/dark-arrow-top-right.svg b/packages/snaps-simulator/src/assets/icons/dark-arrow-top-right.svg deleted file mode 100644 index ed42d8f0cc..0000000000 --- a/packages/snaps-simulator/src/assets/icons/dark-arrow-top-right.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/divider.svg b/packages/snaps-simulator/src/assets/icons/divider.svg deleted file mode 100644 index 0832bcb475..0000000000 --- a/packages/snaps-simulator/src/assets/icons/divider.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/dot.svg b/packages/snaps-simulator/src/assets/icons/dot.svg deleted file mode 100644 index 8f546a5e96..0000000000 --- a/packages/snaps-simulator/src/assets/icons/dot.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/drag.svg b/packages/snaps-simulator/src/assets/icons/drag.svg deleted file mode 100644 index be6ce06118..0000000000 --- a/packages/snaps-simulator/src/assets/icons/drag.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/error-triangle.svg b/packages/snaps-simulator/src/assets/icons/error-triangle.svg deleted file mode 100644 index 44c972dbb1..0000000000 --- a/packages/snaps-simulator/src/assets/icons/error-triangle.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/form.svg b/packages/snaps-simulator/src/assets/icons/form.svg deleted file mode 100644 index 25f96a10c9..0000000000 --- a/packages/snaps-simulator/src/assets/icons/form.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/github-dark.svg b/packages/snaps-simulator/src/assets/icons/github-dark.svg deleted file mode 100644 index 2e8cbde6ba..0000000000 --- a/packages/snaps-simulator/src/assets/icons/github-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/github.svg b/packages/snaps-simulator/src/assets/icons/github.svg deleted file mode 100644 index 410ed692db..0000000000 --- a/packages/snaps-simulator/src/assets/icons/github.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/heading.svg b/packages/snaps-simulator/src/assets/icons/heading.svg deleted file mode 100644 index 9068929010..0000000000 --- a/packages/snaps-simulator/src/assets/icons/heading.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/image.svg b/packages/snaps-simulator/src/assets/icons/image.svg deleted file mode 100644 index 27e5c5a580..0000000000 --- a/packages/snaps-simulator/src/assets/icons/image.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/input.svg b/packages/snaps-simulator/src/assets/icons/input.svg deleted file mode 100644 index 3920b63a8e..0000000000 --- a/packages/snaps-simulator/src/assets/icons/input.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/insights.svg b/packages/snaps-simulator/src/assets/icons/insights.svg deleted file mode 100644 index 0062769b5d..0000000000 --- a/packages/snaps-simulator/src/assets/icons/insights.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/snaps-simulator/src/assets/icons/json-rpc.svg b/packages/snaps-simulator/src/assets/icons/json-rpc.svg deleted file mode 100644 index 808cd66509..0000000000 --- a/packages/snaps-simulator/src/assets/icons/json-rpc.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/snaps-simulator/src/assets/icons/link-out.svg b/packages/snaps-simulator/src/assets/icons/link-out.svg deleted file mode 100644 index dc4dfb103b..0000000000 --- a/packages/snaps-simulator/src/assets/icons/link-out.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/manifest.svg b/packages/snaps-simulator/src/assets/icons/manifest.svg deleted file mode 100644 index 63de63e41b..0000000000 --- a/packages/snaps-simulator/src/assets/icons/manifest.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/snaps-simulator/src/assets/icons/moon.svg b/packages/snaps-simulator/src/assets/icons/moon.svg deleted file mode 100644 index 7f499ca0ee..0000000000 --- a/packages/snaps-simulator/src/assets/icons/moon.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/panel.svg b/packages/snaps-simulator/src/assets/icons/panel.svg deleted file mode 100644 index 0ea72660a5..0000000000 --- a/packages/snaps-simulator/src/assets/icons/panel.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/play-error.svg b/packages/snaps-simulator/src/assets/icons/play-error.svg deleted file mode 100644 index ed7c582aa2..0000000000 --- a/packages/snaps-simulator/src/assets/icons/play-error.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/packages/snaps-simulator/src/assets/icons/play-muted.svg b/packages/snaps-simulator/src/assets/icons/play-muted.svg deleted file mode 100644 index cc80186374..0000000000 --- a/packages/snaps-simulator/src/assets/icons/play-muted.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/snaps-simulator/src/assets/icons/play-success.svg b/packages/snaps-simulator/src/assets/icons/play-success.svg deleted file mode 100644 index 503cc279e5..0000000000 --- a/packages/snaps-simulator/src/assets/icons/play-success.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/packages/snaps-simulator/src/assets/icons/play.svg b/packages/snaps-simulator/src/assets/icons/play.svg deleted file mode 100644 index 23aa61fee5..0000000000 --- a/packages/snaps-simulator/src/assets/icons/play.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/snaps-simulator/src/assets/icons/snap-error.svg b/packages/snaps-simulator/src/assets/icons/snap-error.svg deleted file mode 100644 index 9c3c6a659b..0000000000 --- a/packages/snaps-simulator/src/assets/icons/snap-error.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/packages/snaps-simulator/src/assets/icons/snap.svg b/packages/snaps-simulator/src/assets/icons/snap.svg deleted file mode 100644 index a06fab3d7d..0000000000 --- a/packages/snaps-simulator/src/assets/icons/snap.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/packages/snaps-simulator/src/assets/icons/text-bubble.svg b/packages/snaps-simulator/src/assets/icons/text-bubble.svg deleted file mode 100644 index 1b1202153e..0000000000 --- a/packages/snaps-simulator/src/assets/icons/text-bubble.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/packages/snaps-simulator/src/assets/icons/text.svg b/packages/snaps-simulator/src/assets/icons/text.svg deleted file mode 100644 index 309f57276c..0000000000 --- a/packages/snaps-simulator/src/assets/icons/text.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/snaps-simulator/src/assets/icons/ui.svg b/packages/snaps-simulator/src/assets/icons/ui.svg deleted file mode 100644 index aff8f9aa6b..0000000000 --- a/packages/snaps-simulator/src/assets/icons/ui.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/packages/snaps-simulator/src/assets/logo-dark.svg b/packages/snaps-simulator/src/assets/logo-dark.svg deleted file mode 100644 index 6f627f30fe..0000000000 --- a/packages/snaps-simulator/src/assets/logo-dark.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/snaps-simulator/src/assets/logo.svg b/packages/snaps-simulator/src/assets/logo.svg deleted file mode 100644 index 60252b600b..0000000000 --- a/packages/snaps-simulator/src/assets/logo.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/snaps-simulator/src/components/Author.test.tsx b/packages/snaps-simulator/src/components/Author.test.tsx deleted file mode 100644 index add0e148f6..0000000000 --- a/packages/snaps-simulator/src/components/Author.test.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Author } from './Author'; -import { render } from '../utils'; - -describe('Author', () => { - it('renders', () => { - expect(() => - render( - , - ), - ).not.toThrow(); - }); -}); diff --git a/packages/snaps-simulator/src/components/Author.tsx b/packages/snaps-simulator/src/components/Author.tsx deleted file mode 100644 index f942c415a3..0000000000 --- a/packages/snaps-simulator/src/components/Author.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Flex, Text } from '@chakra-ui/react'; -import type { FunctionComponent } from 'react'; - -import { SnapIcon } from './SnapIcon'; - -type AuthorProps = { - snapName: string; - snapId: string; -}; - -export const Author: FunctionComponent = ({ - snapName, - snapId, -}) => ( - - - - - {snapName} - - - {snapId} - - - -); diff --git a/packages/snaps-simulator/src/components/Copyable.tsx b/packages/snaps-simulator/src/components/Copyable.tsx deleted file mode 100644 index b77ae584b5..0000000000 --- a/packages/snaps-simulator/src/components/Copyable.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { Flex, Text } from '@chakra-ui/react'; -import type { FunctionComponent } from 'react'; -import { useEffect, useState } from 'react'; - -import { Icon } from './Icon'; - -export type CopyableProps = { - value: string; -}; - -export const Copyable: FunctionComponent = ({ value }) => { - const [copied, setCopied] = useState(false); - - const handleClick = () => { - navigator.clipboard - .writeText(value) - .then(() => { - setCopied(true); - }) - .catch((error) => { - // eslint-disable-next-line no-console - console.error(error); - }); - }; - - // eslint-disable-next-line consistent-return - useEffect(() => { - if (copied) { - const timeout = setTimeout(() => { - setCopied(false); - }, 2000); - - return () => clearTimeout(timeout); - } - }, [copied]); - - return ( - - - {value} - - - - ); -}; diff --git a/packages/snaps-simulator/src/components/Delineator.tsx b/packages/snaps-simulator/src/components/Delineator.tsx deleted file mode 100644 index 671b7b0be7..0000000000 --- a/packages/snaps-simulator/src/components/Delineator.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { Box, Flex, Text } from '@chakra-ui/react'; -import type { FunctionComponent, ReactNode } from 'react'; - -import { Icon } from './Icon'; - -export type DelineatorProps = { - type: DelineatorType; - snapName: string; - children: ReactNode; -}; - -export enum DelineatorType { - Content = 'content', - Error = 'error', - Insights = 'insights', -} - -const getTitle = (type: DelineatorType, snapName: string) => { - switch (type) { - case DelineatorType.Insights: - return `Insights from ${snapName}`; - case DelineatorType.Error: - return `Error from ${snapName}`; - default: - return `Content from ${snapName}`; - } -}; - -export const Delineator: FunctionComponent = ({ - type, - snapName, - children, -}) => { - const isError = type === DelineatorType.Error; - return ( - - - - - {getTitle(type, snapName)} - - - {children} - - ); -}; diff --git a/packages/snaps-simulator/src/components/Editor.tsx b/packages/snaps-simulator/src/components/Editor.tsx deleted file mode 100644 index 6d94ea859a..0000000000 --- a/packages/snaps-simulator/src/components/Editor.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import type { BoxProps } from '@chakra-ui/react'; -import { Box, useColorMode } from '@chakra-ui/react'; -import type { FunctionComponent } from 'react'; -import type { monaco, MonacoEditorProps } from 'react-monaco-editor'; -import MonacoEditor from 'react-monaco-editor'; - -import { - JSON_RPC_SCHEMA, - JSON_RPC_SCHEMA_URL, - SAMPLE_JSON_RPC_REQUEST, -} from '../features/handlers/json-rpc/schema'; - -export type EditorProps = MonacoEditorProps & BoxProps; - -/** - * Editor component. This uses Monaco Editor to provide a JSON editor. - * - * @param props - The props. - * @param props.border - The border. - * @param props.borderRadius - The border radius. - * @returns The editor component. - */ -export const Editor: FunctionComponent = ({ - border = '1px solid', - ...props -}) => { - const { colorMode } = useColorMode(); - - const handleMount = (editor: typeof monaco) => { - // Define a theme with the proper background - editor.editor.defineTheme('vs-dark-custom', { - base: 'vs-dark', - inherit: true, - rules: [], - colors: { - 'editor.background': '#24272A', - }, - }); - editor.languages.json?.jsonDefaults.setDiagnosticsOptions({ - validate: true, - schemas: [ - { - uri: JSON_RPC_SCHEMA_URL, - fileMatch: ['*'], - schema: JSON_RPC_SCHEMA, - }, - ], - }); - }; - - return ( - - - - ); -}; diff --git a/packages/snaps-simulator/src/components/Icon.test.tsx b/packages/snaps-simulator/src/components/Icon.test.tsx deleted file mode 100644 index ffe8044867..0000000000 --- a/packages/snaps-simulator/src/components/Icon.test.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { Icon } from './Icon'; -import { render } from '../utils'; - -describe('Icon', () => { - it('renders', () => { - expect(() => render()).not.toThrow(); - }); -}); diff --git a/packages/snaps-simulator/src/components/Icon.tsx b/packages/snaps-simulator/src/components/Icon.tsx deleted file mode 100644 index c57ee93d3b..0000000000 --- a/packages/snaps-simulator/src/components/Icon.tsx +++ /dev/null @@ -1,260 +0,0 @@ -import type { PropsOf } from '@chakra-ui/react'; -import { Image, useColorMode } from '@chakra-ui/react'; -import { hasProperty } from '@metamask/utils'; -import type { ForwardRefExoticComponent } from 'react'; -import { forwardRef } from 'react'; - -import alertIcon from '../assets/icons/alert.svg'; -import arrowDownIcon from '../assets/icons/arrow-down.svg'; -import arrowRightIcon from '../assets/icons/arrow-right.svg'; -import arrowTopRightIcon from '../assets/icons/arrow-top-right.svg'; -import buttonIcon from '../assets/icons/button.svg'; -import computerIcon from '../assets/icons/computer.svg'; -import configurationDarkIcon from '../assets/icons/configuration-dark.svg'; -import configurationIcon from '../assets/icons/configuration.svg'; -import copiedIcon from '../assets/icons/copied.svg'; -import copyIcon from '../assets/icons/copy.svg'; -import copyableIcon from '../assets/icons/copyable.svg'; -import cronjobIcon from '../assets/icons/cronjob.svg'; -import crossDarkIcon from '../assets/icons/cross-dark.svg'; -import crossIcon from '../assets/icons/cross.svg'; -import darkArrowTopRightIcon from '../assets/icons/dark-arrow-top-right.svg'; -import dividerIcon from '../assets/icons/divider.svg'; -import dotIcon from '../assets/icons/dot.svg'; -import dragIcon from '../assets/icons/drag.svg'; -import errorTriangleIcon from '../assets/icons/error-triangle.svg'; -import formIcon from '../assets/icons/form.svg'; -import gitHubDarkIcon from '../assets/icons/github-dark.svg'; -import gitHubIcon from '../assets/icons/github.svg'; -import headingIcon from '../assets/icons/heading.svg'; -import imageIcon from '../assets/icons/image.svg'; -import inputIcon from '../assets/icons/input.svg'; -import insightsIcon from '../assets/icons/insights.svg'; -import jsonRpcIcon from '../assets/icons/json-rpc.svg'; -import linkOutIcon from '../assets/icons/link-out.svg'; -import manifestIcon from '../assets/icons/manifest.svg'; -import moonIcon from '../assets/icons/moon.svg'; -import panelIcon from '../assets/icons/panel.svg'; -import playErrorIcon from '../assets/icons/play-error.svg'; -import playMutedIcon from '../assets/icons/play-muted.svg'; -import playSuccessIcon from '../assets/icons/play-success.svg'; -import playIcon from '../assets/icons/play.svg'; -import snapErrorIcon from '../assets/icons/snap-error.svg'; -import snapIcon from '../assets/icons/snap.svg'; -import textBubbleIcon from '../assets/icons/text-bubble.svg'; -import textIcon from '../assets/icons/text.svg'; -import uiIcon from '../assets/icons/ui.svg'; - -const DEFAULT_ICONS = { - alert: { - alt: 'Alert', - src: alertIcon, - }, - arrowRight: { - alt: 'Arrow pointing right', - src: arrowRightIcon, - }, - arrowTopRight: { - alt: 'Arrow pointing top right', - src: arrowTopRightIcon, - }, - darkArrowTopRightIcon: { - alt: 'Arrow pointing top right', - src: darkArrowTopRightIcon, - }, - arrowDown: { - alt: 'Arrow pointing down', - src: arrowDownIcon, - }, - textBubble: { - alt: 'Text bubble', - src: textBubbleIcon, - }, - configuration: { - alt: 'Configuration', - src: configurationIcon, - srcDark: configurationDarkIcon, - }, - play: { - alt: 'Play', - src: playIcon, - }, - playMuted: { - alt: 'Play', - src: playMutedIcon, - }, - playSuccess: { - alt: 'Success', - src: playSuccessIcon, - }, - playError: { - alt: 'Error', - src: playErrorIcon, - }, - dot: { - alt: 'OK', - src: dotIcon, - }, - errorTriangle: { - alt: 'Error', - src: errorTriangleIcon, - }, - computer: { - alt: 'Computer', - src: computerIcon, - }, - snap: { - alt: 'Snap', - src: snapIcon, - }, - snapError: { - alt: 'Snap Error', - src: snapErrorIcon, - }, - copy: { - alt: 'Copy', - src: copyIcon, - }, - copied: { - alt: 'Copied', - src: copiedIcon, - }, - moon: { - alt: 'Moon', - src: moonIcon, - }, - manifest: { - alt: 'Manifest', - src: manifestIcon, - }, - gitHub: { - alt: 'GitHub', - src: gitHubIcon, - srcDark: gitHubDarkIcon, - }, - cronjob: { - alt: 'Cronjob', - src: cronjobIcon, - }, - insights: { - alt: 'Insights', - src: insightsIcon, - }, - jsonRpc: { - alt: 'JSON-RPC', - src: jsonRpcIcon, - }, - cross: { - alt: 'Cross', - src: crossIcon, - srcDark: crossDarkIcon, - }, - drag: { - alt: 'Drag', - src: dragIcon, - }, - linkOut: { - alt: 'Link Out', - src: linkOutIcon, - }, - heading: { - alt: 'Heading', - src: headingIcon, - }, - text: { - alt: 'Text', - src: textIcon, - }, - copyable: { - alt: 'Copyable', - src: copyableIcon, - }, - divider: { - alt: 'Divider', - src: dividerIcon, - }, - box: { - alt: 'Box', - src: panelIcon, - }, - ui: { - alt: 'UI', - src: uiIcon, - }, - image: { - alt: 'Image', - src: imageIcon, - }, - button: { - alt: 'Button', - src: buttonIcon, - }, - form: { - alt: 'Form', - src: formIcon, - }, - input: { - alt: 'Input', - src: inputIcon, - }, - field: { - alt: 'Field', - src: inputIcon, - }, -}; - -export type IconName = keyof typeof DEFAULT_ICONS; - -export type IconProps = { - icon: IconName; - alt?: string; - width?: string; - height?: string; -} & PropsOf; - -/** - * Icon component, which renders one of the predefined icons. - * - * The component is based on Chakra UI's {@link Image} component, so all props - * supported by {@link Image} are also supported by this component. - * - * @param props - Icon props. - * @param props.icon - The name of the icon, e.g. 'alert'. - * @param props.alt - The alt text for the icon. - * @param props.width - The width of the icon. Defaults to '32px'. - * @param props.height - The height of the icon. Defaults to '32px'. - * @returns The icon component. - */ -export const Icon: ForwardRefExoticComponent = forwardRef( - ( - { - icon, - alt = DEFAULT_ICONS[icon].alt, - width = '32px', - height = width, - ...props - }, - ref, - ) => { - const { colorMode } = useColorMode(); - - const iconMetadata = DEFAULT_ICONS[icon]; - const defaultSrc = iconMetadata.src; - const darkSrc = hasProperty(iconMetadata, 'srcDark') - ? iconMetadata.srcDark - : iconMetadata.src; - - const src = colorMode === 'light' ? defaultSrc : darkSrc; - - return ( - {alt} - ); - }, -); diff --git a/packages/snaps-simulator/src/components/Link.test.tsx b/packages/snaps-simulator/src/components/Link.test.tsx deleted file mode 100644 index 1bd0890388..0000000000 --- a/packages/snaps-simulator/src/components/Link.test.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { Link } from './Link'; -import { render } from '../utils'; - -describe('Link', () => { - it('renders', () => { - expect(() => render()).not.toThrow(); - }); -}); diff --git a/packages/snaps-simulator/src/components/Link.tsx b/packages/snaps-simulator/src/components/Link.tsx deleted file mode 100644 index 026b57f0a0..0000000000 --- a/packages/snaps-simulator/src/components/Link.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import type { LinkProps as ChakraLinkProps } from '@chakra-ui/react'; -import { Link as ChakraLink } from '@chakra-ui/react'; -import type { FunctionComponent } from 'react'; -import type { LinkProps as RouterLinkProps } from 'react-router-dom'; -import { Link as RouterLink } from 'react-router-dom'; - -type LinkProps = { - to: string; - isExternal?: boolean; -} & ChakraLinkProps & - RouterLinkProps; - -/** - * A link component for internal links. This component is a wrapper around - * Chakra's Link component and React Router's Link component, to use both - * together. - * - * @param props - The props of the component. - * @param props.to - The path to link to. - * @param props.children - The children of the component. - * @param props.isExternal - Whether the link is external or not. - * @returns The link component. - */ -export const Link: FunctionComponent = ({ - to, - isExternal = false, - children, - ...props -}) => { - if (isExternal) { - return ( - - {children} - - ); - } - - return ( - - {children} - - ); -}; diff --git a/packages/snaps-simulator/src/components/Logo.test.tsx b/packages/snaps-simulator/src/components/Logo.test.tsx deleted file mode 100644 index fe0947593d..0000000000 --- a/packages/snaps-simulator/src/components/Logo.test.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { Logo } from './Logo'; -import { render } from '../utils'; - -describe('Logo', () => { - it('renders', () => { - expect(() => render()).not.toThrow(); - }); -}); diff --git a/packages/snaps-simulator/src/components/Logo.tsx b/packages/snaps-simulator/src/components/Logo.tsx deleted file mode 100644 index cb995f55b8..0000000000 --- a/packages/snaps-simulator/src/components/Logo.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Image, useColorMode } from '@chakra-ui/react'; -import type { FunctionComponent } from 'react'; - -import logoDark from '../assets/logo-dark.svg'; -import logo from '../assets/logo.svg'; - -/** - * Render the Snaps Simulator logo. - * - * @returns A React component. - */ -export const Logo: FunctionComponent = () => { - const { colorMode } = useColorMode(); - return ( - MetaMask Snaps Simulator - ); -}; diff --git a/packages/snaps-simulator/src/components/Prefill.test.tsx b/packages/snaps-simulator/src/components/Prefill.test.tsx deleted file mode 100644 index cea5a5b316..0000000000 --- a/packages/snaps-simulator/src/components/Prefill.test.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { Prefill } from './Prefill'; -import { render } from '../utils'; - -describe('Prefill', () => { - it('renders', () => { - expect(() => render(Prefill)).not.toThrow(); - }); -}); diff --git a/packages/snaps-simulator/src/components/Prefill.tsx b/packages/snaps-simulator/src/components/Prefill.tsx deleted file mode 100644 index 45fd7cd239..0000000000 --- a/packages/snaps-simulator/src/components/Prefill.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import type { TagProps } from '@chakra-ui/react'; -import { Tag } from '@chakra-ui/react'; -import type { ReactNode } from 'react'; -import { forwardRef } from 'react'; - -import type { IconName } from './Icon'; -import { Icon } from './Icon'; - -type PrefillProps = TagProps & { - icon?: IconName; - iconLocation?: 'left' | 'right'; - children: ReactNode; -}; - -export const Prefill = forwardRef( - ( - { - children, - icon = 'darkArrowTopRightIcon', - iconLocation = 'right', - ...props - }, - ref, - ) => ( - - {iconLocation === 'left' && ( - - )} - {children} - {iconLocation === 'right' && ( - - )} - - ), -); diff --git a/packages/snaps-simulator/src/components/Root.tsx b/packages/snaps-simulator/src/components/Root.tsx deleted file mode 100644 index 0a8a5a632b..0000000000 --- a/packages/snaps-simulator/src/components/Root.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { ChakraProvider, ColorModeScript } from '@chakra-ui/react'; -import { getBackendOptions, MultiBackend } from '@minoru/react-dnd-treeview'; -import type { FunctionComponent, ReactElement } from 'react'; -import { StrictMode } from 'react'; -import { DndProvider } from 'react-dnd'; -import { Provider } from 'react-redux'; - -import { Notifications } from '../features'; -import type { createStore } from '../store'; -import { theme } from '../theme'; - -export type RootProps = { - store: ReturnType; - children: ReactElement; -}; - -/** - * Render the root component. This is the top-level component that wraps the - * entire application. - * - * @param props - The props. - * @param props.store - The Redux store. - * @param props.children - The children to render. - * @returns The root component. - */ -export const Root: FunctionComponent = ({ store, children }) => ( - - - - - - - {children} - - - - -); diff --git a/packages/snaps-simulator/src/components/SnapIcon.test.tsx b/packages/snaps-simulator/src/components/SnapIcon.test.tsx deleted file mode 100644 index c8bb2615b0..0000000000 --- a/packages/snaps-simulator/src/components/SnapIcon.test.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { SnapIcon } from './SnapIcon'; -import { render } from '../utils'; - -describe('SnapIcon', () => { - it('renders', () => { - expect(() => render()).not.toThrow(); - }); -}); diff --git a/packages/snaps-simulator/src/components/SnapIcon.tsx b/packages/snaps-simulator/src/components/SnapIcon.tsx deleted file mode 100644 index f986b75171..0000000000 --- a/packages/snaps-simulator/src/components/SnapIcon.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { Avatar, Box } from '@chakra-ui/react'; -import type { FunctionComponent } from 'react'; - -import { Icon } from './Icon'; -import { getIcon } from '../features'; -import { useSelector } from '../hooks'; - -export type SnapIconProps = { - snapName: string; -}; - -/** - * A Snap icon, which renders the icon defined in the snap's manifest, or a - * fallback icon if the snap doesn't define one. - * - * @param props - The props. - * @param props.snapName - The name of the snap. - * @returns The Snap icon component. - */ -export const SnapIcon: FunctionComponent = ({ snapName }) => { - const snapIcon = useSelector(getIcon); - - const blob = - snapIcon && new Blob([snapIcon.value], { type: 'image/svg+xml' }); - const blobUrl = blob && URL.createObjectURL(blob); - - return ( - - - - - ); -}; diff --git a/packages/snaps-simulator/src/components/TestConditional.tsx b/packages/snaps-simulator/src/components/TestConditional.tsx deleted file mode 100644 index 69c3420f2d..0000000000 --- a/packages/snaps-simulator/src/components/TestConditional.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import type { FunctionComponent, ReactNode } from 'react'; - -import { IS_TEST_BUILD } from '../utils'; - -export type TestProps = { - children: ReactNode; - isTest?: boolean; -}; - -/** - * Renders the children only if the build is a test build. - * - * @param props - The props. - * @param props.children - The children to render. - * @param props.isTest - Whether to render only in test builds, or only in non-test - * builds. - * @returns The component. - */ -export const TestConditional: FunctionComponent = ({ - children, - isTest = true, -}) => { - if (IS_TEST_BUILD === isTest) { - return <>{children}; - } - - return null; -}; diff --git a/packages/snaps-simulator/src/components/Window.test.tsx b/packages/snaps-simulator/src/components/Window.test.tsx deleted file mode 100644 index 2861bf361f..0000000000 --- a/packages/snaps-simulator/src/components/Window.test.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { Window } from './Window'; -import { render } from '../utils'; - -describe('Window', () => { - it('renders', () => { - expect(() => - render( - - Foo - , - ), - ).not.toThrow(); - }); -}); diff --git a/packages/snaps-simulator/src/components/Window.tsx b/packages/snaps-simulator/src/components/Window.tsx deleted file mode 100644 index 9c393775c5..0000000000 --- a/packages/snaps-simulator/src/components/Window.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Flex } from '@chakra-ui/react'; -import type { FunctionComponent, ReactNode } from 'react'; - -import { Author } from './Author'; - -type WindowProps = { - snapName: string; - snapId: string; - children: ReactNode; - showAuthorship?: boolean; -}; - -/** - * A MetaMask-like window, with a snap authorship pill. - * - * @param props - The props. - * @param props.snapName - The name of the snap. - * @param props.snapId - The ID of the snap. - * @param props.children - The children to render inside the window. - * @param props.showAuthorship - Show the authorship component. - * @returns The window component. - */ -export const Window: FunctionComponent = ({ - snapName, - snapId, - children, - showAuthorship = true, -}) => ( - - {showAuthorship && } - {children} - -); diff --git a/packages/snaps-simulator/src/components/dialogs/AlertDialog.test.tsx b/packages/snaps-simulator/src/components/dialogs/AlertDialog.test.tsx deleted file mode 100644 index 791ac581eb..0000000000 --- a/packages/snaps-simulator/src/components/dialogs/AlertDialog.test.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { Box } from '@metamask/snaps-sdk/jsx'; - -import { AlertDialog } from './AlertDialog'; -import { render } from '../../utils'; - -describe('AlertDialog', () => { - it('renders', () => { - expect(() => - render( - , - ), - ).not.toThrow(); - }); -}); diff --git a/packages/snaps-simulator/src/components/dialogs/AlertDialog.tsx b/packages/snaps-simulator/src/components/dialogs/AlertDialog.tsx deleted file mode 100644 index b5ef44cddc..0000000000 --- a/packages/snaps-simulator/src/components/dialogs/AlertDialog.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Box, Button, Flex } from '@chakra-ui/react'; -import type { JSXElement } from '@metamask/snaps-sdk/jsx'; -import type { FunctionComponent } from 'react'; - -import { Renderer } from '../../features/renderer'; -import { Delineator, DelineatorType } from '../Delineator'; -import { Window } from '../Window'; - -export type AlertDialogProps = { - snapName: string; - snapId: string; - content: JSXElement; - onClose?: () => void; -}; - -/** - * Snap alert dialog. - * - * @param props - The component props. - * @param props.snapName - The snap name. - * @param props.snapId - The snap ID. - * @param props.content - The component to render. - * @param props.onClose - The close callback. - * @returns The component. - */ -export const AlertDialog: FunctionComponent = ({ - snapName, - snapId, - content, - onClose, -}) => ( - - - - - - - - - - -); diff --git a/packages/snaps-simulator/src/components/dialogs/ConfirmationDialog.test.tsx b/packages/snaps-simulator/src/components/dialogs/ConfirmationDialog.test.tsx deleted file mode 100644 index 63c7f2b621..0000000000 --- a/packages/snaps-simulator/src/components/dialogs/ConfirmationDialog.test.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { Box } from '@metamask/snaps-sdk/jsx'; - -import { ConfirmationDialog } from './ConfirmationDialog'; -import { render } from '../../utils'; - -describe('ConfirmationDialog', () => { - it('renders', () => { - expect(() => - render( - , - ), - ).not.toThrow(); - }); -}); diff --git a/packages/snaps-simulator/src/components/dialogs/ConfirmationDialog.tsx b/packages/snaps-simulator/src/components/dialogs/ConfirmationDialog.tsx deleted file mode 100644 index 1b9abf0b8c..0000000000 --- a/packages/snaps-simulator/src/components/dialogs/ConfirmationDialog.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { Box, Button, Flex } from '@chakra-ui/react'; -import type { JSXElement } from '@metamask/snaps-sdk/jsx'; -import type { FunctionComponent } from 'react'; - -import { Renderer } from '../../features/renderer'; -import { Delineator, DelineatorType } from '../Delineator'; -import { Window } from '../Window'; - -export type ConfirmationDialogProps = { - snapName: string; - snapId: string; - content: JSXElement; - onCancel?: () => void; - onApprove?: () => void; -}; - -/** - * Snap confirmation dialog. - * - * @param props - The component props. - * @param props.snapName - The snap name. - * @param props.snapId - The snap ID. - * @param props.content - The component to render. - * @param props.onCancel - The cancel callback. - * @param props.onApprove - The approve callback. - * @returns The component. - */ -export const ConfirmationDialog: FunctionComponent = ({ - snapName, - snapId, - content, - onCancel, - onApprove, -}) => ( - - - - - - - - - - - -); diff --git a/packages/snaps-simulator/src/components/dialogs/PromptDialog.test.tsx b/packages/snaps-simulator/src/components/dialogs/PromptDialog.test.tsx deleted file mode 100644 index aa3d072840..0000000000 --- a/packages/snaps-simulator/src/components/dialogs/PromptDialog.test.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { Box } from '@metamask/snaps-sdk/jsx'; - -import { PromptDialog } from './PromptDialog'; -import { render } from '../../utils'; - -describe('PromptDialog', () => { - it('renders', () => { - expect(() => - render( - , - ), - ).not.toThrow(); - }); -}); diff --git a/packages/snaps-simulator/src/components/dialogs/PromptDialog.tsx b/packages/snaps-simulator/src/components/dialogs/PromptDialog.tsx deleted file mode 100644 index 46c7c9007f..0000000000 --- a/packages/snaps-simulator/src/components/dialogs/PromptDialog.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import { Box, Button, Flex, FormControl, Input } from '@chakra-ui/react'; -import type { JSXElement } from '@metamask/snaps-sdk/jsx'; -import type { FunctionComponent } from 'react'; -import { useForm } from 'react-hook-form'; - -import { Renderer } from '../../features/renderer'; -import { Delineator, DelineatorType } from '../Delineator'; -import { Window } from '../Window'; - -export type PromptDialogProps = { - snapName: string; - snapId: string; - placeholder?: string; - content: JSXElement; - onCancel?: () => void; - onSubmit?: (value: string) => void; -}; - -type PromptForm = { - value: string; -}; - -/** - * Snap prompt dialog. - * - * @param props - The component props. - * @param props.snapName - The snap name. - * @param props.snapId - The snap ID. - * @param props.placeholder - The placeholder text. - * @param props.content - The component to render. - * @param props.onCancel - The cancel callback. - * @param props.onSubmit - The submit callback. The value is passed as the first - * argument. - * @returns The component. - */ -export const PromptDialog: FunctionComponent = ({ - snapName, - snapId, - placeholder, - content, - onCancel, - onSubmit, -}) => { - const { - handleSubmit, - register, - formState: { errors }, - } = useForm({ - defaultValues: { - value: '', - }, - }); - - const onFormSubmit = (data: PromptForm) => { - onSubmit?.(data.value); - }; - - return ( - - - - - {/* eslint-disable-next-line @typescript-eslint/no-misused-promises */} -
- - - -
-
-
- - - - -
- ); -}; diff --git a/packages/snaps-simulator/src/components/dialogs/index.ts b/packages/snaps-simulator/src/components/dialogs/index.ts deleted file mode 100644 index 3d62ddf256..0000000000 --- a/packages/snaps-simulator/src/components/dialogs/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './AlertDialog'; -export * from './ConfirmationDialog'; -export * from './PromptDialog'; diff --git a/packages/snaps-simulator/src/components/index.ts b/packages/snaps-simulator/src/components/index.ts deleted file mode 100644 index 9ee0e8893a..0000000000 --- a/packages/snaps-simulator/src/components/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -// Components that are used in multiple places in the app, such as components -// that are used in multiple routes, can be exported here. Components that are -// only used in one place, such as components that are only used in one route, -// should be exported from their respective feature folder. - -export * from './dialogs'; -export * from './Delineator'; -export * from './Editor'; -export * from './Icon'; -export * from './Logo'; -export * from './Prefill'; -export * from './Root'; -export * from './Link'; -export * from './TestConditional'; -export * from './Window'; -export * from './Copyable'; diff --git a/packages/snaps-simulator/src/contexts/SnapInterface.tsx b/packages/snaps-simulator/src/contexts/SnapInterface.tsx deleted file mode 100644 index 5061949c76..0000000000 --- a/packages/snaps-simulator/src/contexts/SnapInterface.tsx +++ /dev/null @@ -1,202 +0,0 @@ -import { UserInputEventType } from '@metamask/snaps-sdk'; -import type { FormState, State } from '@metamask/snaps-sdk'; -import { HandlerType } from '@metamask/snaps-utils'; -import debounce from 'lodash.debounce'; -import throttle from 'lodash.throttle'; -import type { FunctionComponent, ReactNode } from 'react'; -import { createContext, useContext } from 'react'; - -import { mergeValue } from './utils'; -import { - getSnapInterfaceController, - getSnapInterface, - sendRequest, - setSnapInterfaceState, -} from '../features'; -import { useDispatch, useSelector } from '../hooks'; - -/** - * A no-op function. - * Used when there is no Snap Interface to interact with. - */ -const noOp = () => { - /* No Op */ -}; - -export type GetValue = (name: string, form?: string) => State | undefined; - -export type HandleInputChange = ( - name: string, - value: string | null, - form?: string, -) => void; - -export type HandleEvent = (args: { - event: UserInputEventType; - name?: string; - value?: State; -}) => void; - -export type SnapInterfaceContextType = { - getValue: GetValue; - handleInputChange: HandleInputChange; - handleEvent: HandleEvent; -}; - -const initialState = { - getValue: noOp as GetValue, - handleInputChange: noOp as HandleInputChange, - handleEvent: noOp as HandleEvent, -}; - -export const SnapInterfaceContext = - createContext(initialState); - -export type SnapInterfaceContextProviderProps = { - children: ReactNode; -}; - -// We want button clicks to be instant and therefore use throttling -// to protect the Snap -// Any event not in this array will be debounced instead of throttled -const THROTTLED_EVENTS = [ - UserInputEventType.ButtonClickEvent, - UserInputEventType.FormSubmitEvent, -]; - -/** - * A provider for the Snap Interface context. - * This context provides functions to interact with the Snap Interface. - * - * @param props - The props of the component. - * @param props.children - The children of the component. - * @returns A provider for the Snap Interface context. - */ -export const SnapInterfaceContextProvider: FunctionComponent< - SnapInterfaceContextProviderProps -> = ({ children }) => { - const dispatch = useDispatch(); - const snapInterface = useSelector(getSnapInterface); - const snapInterfaceController = useSelector(getSnapInterfaceController); - - if (!snapInterface) { - return ( - - {children} - - ); - } - - const { id, state } = snapInterface; - - /** - * Send a request to the Snap. - * - * @param event - The event type. - * @param name - The name of the component emitting the event. - * @param value - The value of the component emitting the event. - */ - const rawSnapRequestFunction = ( - event: UserInputEventType, - name?: string, - value?: State | FormState, - ) => { - dispatch( - sendRequest({ - origin: 'metamask', - handler: HandlerType.OnUserInput, - request: { - jsonrpc: '2.0', - method: ' ', - params: { - event: { - type: event, - // TODO: Allow null in the types and simplify this - ...(name !== undefined && name !== null ? { name } : {}), - ...(value !== undefined && value !== null ? { value } : {}), - }, - id, - }, - }, - }), - ); - }; - - /** - * Debounce the request to the Snap. - */ - const snapRequestDebounced = debounce(rawSnapRequestFunction, 200); - - /** - * Throttle the request to the Snap. - */ - const snapRequestThrottled = throttle(rawSnapRequestFunction, 200); - - /** - * Handle the submission of an user input event to the Snap. - * - * @param options - An options bag. - * @param options.event - The event type. - * @param options.name - The name of the component emitting the event. - * @param options.value - The value of the component emitting the event. - */ - const handleEvent: HandleEvent = ({ - event, - name, - value = name ? ((state as FormState)[name] ?? undefined) : undefined, - }) => { - const fn = THROTTLED_EVENTS.includes(event) - ? snapRequestThrottled - : snapRequestDebounced; - fn(event, name, value); - }; - - const getValue: GetValue = (name, form) => { - const value = form - ? (state[form] as FormState)?.[name] - : (state as FormState)?.[name]; - - if (value) { - return value; - } - - return undefined; - }; - - /** - * Handle the change of an input value. - * - * @param name - The name of the input. - * @param value - The new value of the input. - * @param form - The form containing the input. - */ - const handleInputChange: HandleInputChange = (name, value, form) => { - const newState = mergeValue(state, name, value, form); - - snapInterfaceController?.updateInterfaceState(id, newState); - dispatch(setSnapInterfaceState(newState)); - - handleEvent({ - event: UserInputEventType.InputChangeEvent, - name, - value: value ?? '', - }); - }; - - return ( - - {children} - - ); -}; - -/** - * Get the Snap Interface context. - * - * @returns The Snap Interface context. - */ -export function useSnapInterfaceContext() { - return useContext(SnapInterfaceContext); -} diff --git a/packages/snaps-simulator/src/contexts/index.ts b/packages/snaps-simulator/src/contexts/index.ts deleted file mode 100644 index c4f7aad197..0000000000 --- a/packages/snaps-simulator/src/contexts/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './SnapInterface'; diff --git a/packages/snaps-simulator/src/contexts/utils.test.ts b/packages/snaps-simulator/src/contexts/utils.test.ts deleted file mode 100644 index 18736e9e70..0000000000 --- a/packages/snaps-simulator/src/contexts/utils.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { mergeValue } from './utils'; - -describe('mergeValue', () => { - it('merges a value outside of a form', () => { - const state = { foo: 'bar' }; - - const result = mergeValue(state, 'foo', 'baz'); - - expect(result).toStrictEqual({ foo: 'baz' }); - }); - - it('merges a value inside of a form', () => { - const state = { foo: { bar: 'baz' } }; - - const result = mergeValue(state, 'bar', 'test', 'foo'); - - expect(result).toStrictEqual({ foo: { bar: 'test' } }); - }); -}); diff --git a/packages/snaps-simulator/src/contexts/utils.ts b/packages/snaps-simulator/src/contexts/utils.ts deleted file mode 100644 index 70e9cf8e70..0000000000 --- a/packages/snaps-simulator/src/contexts/utils.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { FormState, InterfaceState } from '@metamask/snaps-sdk'; - -/** - * Merge a new input value in the interface state. - * - * @param state - The current interface state. - * @param name - The input name. - * @param value - The input value. - * @param form - The name of the form containing the input. - * Optional if the input is not contained in a form. - * @returns The interface state with the new value merged in. - */ -export const mergeValue = ( - state: InterfaceState, - name: string, - value: string | null, - form?: string, -): InterfaceState => { - if (form) { - return { - ...state, - [form]: { - ...(state[form] as FormState), - [name]: value, - }, - }; - } - return { ...state, [name]: value }; -}; diff --git a/packages/snaps-simulator/src/entry.tsx b/packages/snaps-simulator/src/entry.tsx deleted file mode 100644 index fb004b6277..0000000000 --- a/packages/snaps-simulator/src/entry.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { assert } from '@metamask/utils'; -import { createRoot } from 'react-dom/client'; - -import { setWindowApi } from './api'; -import { App } from './App'; -import { Root } from './components'; -import { createStore } from './store'; -import { IS_TEST_BUILD } from './utils'; - -// eslint-disable-next-line import-x/no-unassigned-import -import './assets/fonts/fonts.css'; - -const rootElement = document.getElementById('root'); -assert(rootElement, 'Root element not found.'); - -const store = createStore(); -const root = createRoot(rootElement); - -if (IS_TEST_BUILD) { - setWindowApi(store); -} - -root.render( - - - , -); diff --git a/packages/snaps-simulator/src/features/builder/Builder.tsx b/packages/snaps-simulator/src/features/builder/Builder.tsx deleted file mode 100644 index 8f4b7e4ffb..0000000000 --- a/packages/snaps-simulator/src/features/builder/Builder.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import { - Box as ChakraBox, - Flex, - Tab, - TabList, - TabPanel, - TabPanels, - Tabs, -} from '@chakra-ui/react'; -import { Box, type JSXElement } from '@metamask/snaps-sdk/jsx'; -import type { NodeModel } from '@minoru/react-dnd-treeview'; -import type { FunctionComponent } from 'react'; -import { useState } from 'react'; - -import { TemplateComponentList, NodeTree, NodeRenderer } from './components'; -import { boxToCode, nodeModelsToComponent } from './utils'; -import { Editor } from '../../components'; - -export const Builder: FunctionComponent = () => { - const [id, setId] = useState(2); - const [items, setItems] = useState[]>([ - { - id: 1, - parent: 0, - text: 'Box', - droppable: true, - data: Box({ children: null }), - }, - ]); - - const incrementId = () => { - setId((state) => state + 1); - }; - - return ( - - - - - - Builder - - - - - - - - - - - - - Result - Code - - - - - - - - - - - - - - ); -}; diff --git a/packages/snaps-simulator/src/features/builder/components/BaseNode.tsx b/packages/snaps-simulator/src/features/builder/components/BaseNode.tsx deleted file mode 100644 index 6cc47f633e..0000000000 --- a/packages/snaps-simulator/src/features/builder/components/BaseNode.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { Flex, Text } from '@chakra-ui/react'; -import type { JSXElement } from '@metamask/snaps-sdk/jsx'; -import { assert } from '@metamask/utils'; -import type { NodeModel } from '@minoru/react-dnd-treeview'; -import type { FunctionComponent, ReactNode } from 'react'; - -import type { IconName } from '../../../components'; -import { Icon } from '../../../components'; - -export type BaseNodeProps = { - node: NodeModel; - isDragging: boolean; - children?: ReactNode; - onClose?: ((node: NodeModel) => void) | undefined; -}; - -export const BaseNode: FunctionComponent = ({ - node, - isDragging, - children, - onClose, -}) => { - assert(node.data?.type, 'Node must have a type.'); - - const handleClick = () => { - onClose?.(node); - }; - - return ( - 1 ? 'move' : 'default'} - > - - - {node.data.type} - - {children} - {Number(node.id) >= 2 && ( - - )} - - ); -}; diff --git a/packages/snaps-simulator/src/features/builder/components/EditableNodeInput.tsx b/packages/snaps-simulator/src/features/builder/components/EditableNodeInput.tsx deleted file mode 100644 index 15388985bc..0000000000 --- a/packages/snaps-simulator/src/features/builder/components/EditableNodeInput.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { Input as ChakraInput } from '@chakra-ui/react'; -import type { ChangeEvent, FunctionComponent } from 'react'; -import { useState } from 'react'; - -type EditableNodeInputProps = { - placeholder: string; - defaultValue: string | undefined; - onChange?: (value: string) => void; -}; - -/** - * A text field for an editable node text field, which renders an input field in the editable component. - * - * @param props - The props of the component. - * @param props.placeholder - The placeholder of the input field. - * @param props.defaultValue - The property default value. - * @param props.onChange - A function to call when the dropdown changes. - * @returns An editable node text field component. - */ -export const EditableNodeInput: FunctionComponent = ({ - placeholder, - defaultValue, - onChange, -}) => { - const [value, setValue] = useState(defaultValue); - - const handleChange = (event: ChangeEvent) => { - setValue(event.target.value); - onChange?.(event.target.value); - }; - - return ( - - ); -}; diff --git a/packages/snaps-simulator/src/features/builder/components/EditableNodeSelect.tsx b/packages/snaps-simulator/src/features/builder/components/EditableNodeSelect.tsx deleted file mode 100644 index 146f68cad1..0000000000 --- a/packages/snaps-simulator/src/features/builder/components/EditableNodeSelect.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { Select } from '@chakra-ui/react'; -import type { ChangeEvent, FunctionComponent } from 'react'; -import { useState } from 'react'; - -type EditableNodeSelectProps = { - defaultValue: string | undefined; - options: string[]; - onChange: (value: string) => void; -}; - -/** - * A dropdown for an editable node enum field, which renders a dropdown field in the editable component. - * - * @param props - The props of the component. - * @param props.defaultValue - The property default value. - * @param props.options - The options of the dropdown. - * @param props.onChange - A function to call when the dropdown changes. - * @returns An editable node dropdown component. - */ -export const EditableNodeSelect: FunctionComponent = ({ - defaultValue, - options, - onChange, -}) => { - const [value, setValue] = useState(defaultValue); - - const handleChange = (event: ChangeEvent) => { - setValue(event.target.value); - onChange(event.target.value); - }; - - return ( - - ); -}; diff --git a/packages/snaps-simulator/src/features/builder/components/ErrorBoundary.tsx b/packages/snaps-simulator/src/features/builder/components/ErrorBoundary.tsx deleted file mode 100644 index 84fb5df3a2..0000000000 --- a/packages/snaps-simulator/src/features/builder/components/ErrorBoundary.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import type { ReactNode } from 'react'; -import { Component } from 'react'; - -type ErrorBoundaryProps = { - fallback: ReactNode; - children: ReactNode; -}; - -type ErrorBoundaryState = { - hasError: boolean; -}; - -export class ErrorBoundary extends Component< - ErrorBoundaryProps, - ErrorBoundaryState -> { - constructor(props: ErrorBoundaryProps) { - super(props); - - this.state = { hasError: false }; - } - - componentDidUpdate(prevProps: ErrorBoundaryProps) { - if (prevProps.children !== this.props.children) { - this.setState({ hasError: false }); - } - } - - static getDerivedStateFromError() { - // Update state so the next render will show the fallback UI. - return { hasError: true }; - } - - render() { - if (this.state.hasError) { - // You can render any custom fallback UI - return this.props.fallback; - } - - return this.props.children; - } -} diff --git a/packages/snaps-simulator/src/features/builder/components/MultiEditableNode.tsx b/packages/snaps-simulator/src/features/builder/components/MultiEditableNode.tsx deleted file mode 100644 index 70cd20853f..0000000000 --- a/packages/snaps-simulator/src/features/builder/components/MultiEditableNode.tsx +++ /dev/null @@ -1,153 +0,0 @@ -import { Box } from '@chakra-ui/react'; -import { ButtonType, InputType } from '@metamask/snaps-sdk'; -import type { - ButtonElement, - FieldElement, - FormElement, - InputElement, -} from '@metamask/snaps-sdk/jsx'; -import type { FunctionComponent } from 'react'; - -import { BaseNode } from './BaseNode'; -import { EditableNodeInput } from './EditableNodeInput'; -import { EditableNodeSelect } from './EditableNodeSelect'; -import type { EditableNodeProps } from '../../../types'; - -export type MultiEditableComponent = - | ButtonElement - | InputElement - | FormElement - | FieldElement; - -enum FieldType { - String = 'string', - Dropdown = 'dropdown', -} - -type MultiEditableNodes = Record< - MultiEditableComponent['type'], - Record< - string, - { type: FieldType.String } | { type: FieldType.Dropdown; values: string[] } - > ->; - -export const MULTI_EDITABLE_NODES: MultiEditableNodes = { - Input: { - name: { - type: FieldType.String, - }, - label: { - type: FieldType.String, - }, - placeholder: { - type: FieldType.String, - }, - value: { - type: FieldType.String, - }, - type: { - type: FieldType.Dropdown, - values: [InputType.Text, InputType.Number, InputType.Password], - }, - error: { - type: FieldType.String, - }, - }, - Button: { - name: { - type: FieldType.String, - }, - value: { - type: FieldType.String, - }, - variant: { - type: FieldType.Dropdown, - values: ['primary', 'destructive'], - }, - type: { - type: FieldType.Dropdown, - values: [ButtonType.Button, ButtonType.Submit], - }, - children: { - type: FieldType.String, - }, - }, - Form: { - name: { - type: FieldType.String, - }, - }, - Field: { - label: { - type: FieldType.String, - }, - error: { - type: FieldType.String, - }, - }, -}; - -/** - * An editable node with multiple fields, which renders an editable component in the builder. - * - * @param props - The props of the component. - * @param props.node - The editable node to render. - * @param props.depth - The depth of the node in the tree. - * @param props.isDragging - Whether the node is being dragged. - * @param props.onChange - A function to call when the node changes. - * @param props.onClose - A function to call when the node is closed. - * @returns An editable node component. - */ -export const MultiEditableNode: FunctionComponent< - EditableNodeProps -> = ({ node, depth, isDragging, onChange, onClose }) => { - if (!node.data) { - return null; - } - - const nodeDataOptions = MULTI_EDITABLE_NODES[node.data.type]; - return ( - - - - {Object.keys(nodeDataOptions).map((key) => { - const property = nodeDataOptions[key]; - - const handleChange = (value: string) => { - onChange?.(node, key, value); - }; - - if (property.type === FieldType.String) { - return ( - - ); - } - - if (property.type === FieldType.Dropdown) { - return ( - - ); - } - - return null; - })} - - - - ); -}; diff --git a/packages/snaps-simulator/src/features/builder/components/Node.tsx b/packages/snaps-simulator/src/features/builder/components/Node.tsx deleted file mode 100644 index 173db192e2..0000000000 --- a/packages/snaps-simulator/src/features/builder/components/Node.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { Box } from '@chakra-ui/react'; -import type { JSXElement } from '@metamask/snaps-sdk/jsx'; -import { assert } from '@metamask/utils'; -import type { NodeModel } from '@minoru/react-dnd-treeview'; -import type { FunctionComponent } from 'react'; - -import { BaseNode } from './BaseNode'; -import type { MultiEditableComponent } from './MultiEditableNode'; -import { MULTI_EDITABLE_NODES, MultiEditableNode } from './MultiEditableNode'; -import type { TextEditableComponent } from './TextEditableNode'; -import { TEXT_EDITABLE_NODES, TextEditableNode } from './TextEditableNode'; - -type NodeProps = { - node: NodeModel; - depth: number; - isDragging: boolean; - onChange: (node: NodeModel, key: string, value: string) => void; - onClose?: ((node: NodeModel) => void) | undefined; -}; - -/** - * A node, which renders a component in the builder. The node can be editable or - * non-editable. - * - * @param props - The props of the component. - * @param props.node - The node to render. - * @param props.depth - The depth of the node in the tree. - * @param props.isDragging - Whether the node is being dragged. - * @param props.onChange - A function to call when the node changes. - * @param props.onClose - A function to call when the node is closed. - * @returns A node component. - */ -export const Node: FunctionComponent = ({ - node, - depth, - isDragging, - onChange, - onClose, -}) => { - assert(node.data?.type, 'Node must have a type.'); - if (TEXT_EDITABLE_NODES.includes(node.data.type)) { - return ( - } - depth={depth} - isDragging={isDragging} - onChange={onChange} - onClose={onClose} - /> - ); - } - - if (Object.keys(MULTI_EDITABLE_NODES).includes(node.data.type)) { - return ( - } - depth={depth} - isDragging={isDragging} - onChange={onChange} - onClose={onClose} - /> - ); - } - - return ( - - - - ); -}; diff --git a/packages/snaps-simulator/src/features/builder/components/NodeRenderer.tsx b/packages/snaps-simulator/src/features/builder/components/NodeRenderer.tsx deleted file mode 100644 index b741c4c1f1..0000000000 --- a/packages/snaps-simulator/src/features/builder/components/NodeRenderer.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { Box, Text } from '@chakra-ui/react'; -import type { JSXElement } from '@metamask/snaps-sdk/jsx'; -import type { NodeModel } from '@minoru/react-dnd-treeview'; -import type { FunctionComponent } from 'react'; -import { useMemo } from 'react'; -import { useSelector } from 'react-redux'; - -import { ErrorBoundary } from './ErrorBoundary'; -import { - Delineator, - DelineatorType, - Window, - Copyable, -} from '../../../components'; -import { getSnapId } from '../../configuration'; -import { Renderer } from '../../renderer'; -import { getSnapName } from '../../simulation'; -import { nodeModelsToComponent } from '../utils'; - -export type NodeRendererProps = { - items: NodeModel[]; -}; - -/** - * A node renderer, which renders the result of a node tree. The tree is - * converted to a component, which is then rendered in the MetaMask window. - * - * @param props - The props of the component. - * @param props.items - The items to render in the tree. - * @returns A node renderer component. - */ -export const NodeRenderer: FunctionComponent = ({ - items, -}) => { - const snapId = useSelector(getSnapId); - const snapName = useSelector(getSnapName) ?? 'Unknown'; - const node = useMemo(() => nodeModelsToComponent(items), [items]); - - return ( - - - - - Contact the creators of {snapName} for further support. - - - - } - > - - - - - - - ); -}; diff --git a/packages/snaps-simulator/src/features/builder/components/NodeTree.tsx b/packages/snaps-simulator/src/features/builder/components/NodeTree.tsx deleted file mode 100644 index a6bd72f454..0000000000 --- a/packages/snaps-simulator/src/features/builder/components/NodeTree.tsx +++ /dev/null @@ -1,168 +0,0 @@ -import { Box, Flex } from '@chakra-ui/react'; -import type { JSXElement } from '@metamask/snaps-sdk/jsx'; -import type { - NodeModel, - NodeRender, - TreeMethods, - TreeProps, -} from '@minoru/react-dnd-treeview'; -import { Tree } from '@minoru/react-dnd-treeview'; -import type { FunctionComponent } from 'react'; -import { useEffect, useRef } from 'react'; - -import { Node } from './Node'; -import { Start } from './Start'; -import { canDropElement } from '../utils'; - -export type NodeTreeProps = { - items: NodeModel[]; - setItems: (items: NodeModel[]) => void; -}; - -/** - * A node tree, which renders the UI components in the builder. - * - * @param props - The props of the component. - * @param props.items - The items to render in the tree. - * @param props.setItems - A function to set the items in the tree. - * @returns A node tree component. - */ -export const NodeTree: FunctionComponent = ({ - items, - setItems, -}) => { - const ref = useRef(null); - - const handleChange = ( - node: NodeModel, - key: string, - value: string, - ) => { - // TODO: This code is a mess. - const newItems: any = items.map((item) => { - if (item.id === node.id) { - return { - ...item, - data: { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - type: item.data!.type, - ...item.data, - props: { - ...item.data?.props, - [key]: value, - }, - }, - text: value, - }; - } - - return item; - }); - - setItems(newItems); - }; - - const handleDrop = (newItems: NodeModel[]) => { - setItems(newItems); - }; - - const handleClose = (node: NodeModel) => { - const newItems = items.filter( - (item) => item.id !== node.id && item.parent !== node.id, - ); - - setItems(newItems); - }; - - const handleRender: NodeRender = ( - node, - { depth, isDragging }, - ) => { - if (items.length <= 1) { - return ; - } - - return ( - - ); - }; - - const handleRenderPlaceholder = () => { - return ; - }; - - const handleCanDrag = (node?: NodeModel) => { - if (node) { - return Number(node.id) >= 2; - } - - return false; - }; - - const handleCanDrop: TreeProps['canDrop'] = ( - _tree, - { dropTarget, dropTargetId, dragSource }, - ) => { - if (dropTargetId && dragSource?.data) { - return ( - canDropElement(dropTarget?.data, dragSource?.data) && - dropTarget?.droppable && - Number(dropTargetId) > 0 - ); - } - - return false; - }; - - useEffect(() => { - if (ref.current) { - ref.current.openAll(); - } - }, [items, ref]); - - return ( - ul': { - display: 'flex', - flexDirection: 'column', - flex: 1, - marginY: '4', - '& > li': { - display: 'flex', - flexDirection: 'column', - flex: 1, - marginTop: '0', - }, - }, - ul: { listStyleType: 'none' }, - li: { marginTop: '2' }, - }} - > - - - ); -}; diff --git a/packages/snaps-simulator/src/features/builder/components/Start.tsx b/packages/snaps-simulator/src/features/builder/components/Start.tsx deleted file mode 100644 index de34a83134..0000000000 --- a/packages/snaps-simulator/src/features/builder/components/Start.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Flex, Heading, Text } from '@chakra-ui/react'; -import type { FunctionComponent } from 'react'; - -import { Icon } from '../../../components'; - -export const Start: FunctionComponent = () => ( - - - - Drag components in here - - - Build your UI piece-by-piece using the -
- predefined components above. -
-
-); diff --git a/packages/snaps-simulator/src/features/builder/components/TemplateComponent.tsx b/packages/snaps-simulator/src/features/builder/components/TemplateComponent.tsx deleted file mode 100644 index 816832eb7d..0000000000 --- a/packages/snaps-simulator/src/features/builder/components/TemplateComponent.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { Box } from '@chakra-ui/react'; -import type { JSXElement } from '@metamask/snaps-sdk/jsx'; -import type { NodeModel } from '@minoru/react-dnd-treeview'; -import type { FunctionComponent } from 'react'; -import { useDrag } from 'react-dnd'; - -import type { IconName } from '../../../components'; -import { Prefill } from '../../../components'; - -type TemplateComponentProps = { - node: NodeModel; - icon: IconName; - incrementId: () => void; -}; - -export const TemplateComponent: FunctionComponent = ({ - node, - icon, - incrementId, -}) => { - const [, drag] = useDrag({ - type: 'template', - item: node, - end: (item, monitor) => { - const dropResult = monitor.getDropResult(); - if (item && dropResult) { - incrementId(); - } - }, - }); - - return ( - - {node.text} - - ); -}; diff --git a/packages/snaps-simulator/src/features/builder/components/TemplateComponentList.tsx b/packages/snaps-simulator/src/features/builder/components/TemplateComponentList.tsx deleted file mode 100644 index b89b749f69..0000000000 --- a/packages/snaps-simulator/src/features/builder/components/TemplateComponentList.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import { - Box as ChakraBox, - Flex, - List, - ListItem, - Text as ChakraText, -} from '@chakra-ui/react'; -import type { JSXElement } from '@metamask/snaps-sdk/jsx'; -import { - Box, - Heading, - Text, - Divider, - Copyable, - Image, - Button, - Form, - Input, - Field, -} from '@metamask/snaps-sdk/jsx'; -import type { FunctionComponent } from 'react'; - -import { TemplateComponent } from './TemplateComponent'; -import type { IconName } from '../../../components'; - -type TemplateComponent = { - icon: IconName; - text: string; - data: JSXElement; - droppable: boolean; -}; - -const SVG = ` - - - - - -`; - -const TEMPLATE_COMPONENTS: TemplateComponent[] = [ - { - icon: 'box', - text: 'Box', - data: Box({ children: null }), - droppable: true, - }, - { - icon: 'heading', - text: 'Heading', - data: Heading({ children: 'Heading' }), - droppable: false, - }, - { - icon: 'text', - text: 'Text', - data: Text({ children: 'Text' }), - droppable: false, - }, - { - icon: 'divider', - text: 'Divider', - data: Divider({}), - droppable: false, - }, - { - icon: 'copyable', - text: 'Copyable', - data: Copyable({ value: 'Text to copy' }), - droppable: false, - }, - { - icon: 'image', - text: 'Image', - data: Image({ src: SVG }), - droppable: false, - }, - { - icon: 'button', - text: 'Button', - data: Button({ children: 'Button' }), - droppable: false, - }, - { - icon: 'form', - text: 'Form', - data: Form({ - name: 'form', - children: [], - }), - droppable: true, - }, - { - icon: 'field', - text: 'Field', - data: Field({ - // @ts-expect-error - children is required - children: null, - }), - droppable: true, - }, - - { - icon: 'input', - text: 'Input', - data: Input({ name: 'input' }), - droppable: false, - }, -]; - -export type ComponentsListProps = { - nextId: number; - incrementId: () => void; -}; - -export const TemplateComponentList: FunctionComponent = ({ - nextId, - incrementId, -}) => ( - - - Components - - - {TEMPLATE_COMPONENTS.map((component) => ( - - - - ))} - - -); diff --git a/packages/snaps-simulator/src/features/builder/components/TextEditableNode.tsx b/packages/snaps-simulator/src/features/builder/components/TextEditableNode.tsx deleted file mode 100644 index 89add7e05d..0000000000 --- a/packages/snaps-simulator/src/features/builder/components/TextEditableNode.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { Box, Input as ChakraInput } from '@chakra-ui/react'; -import type { - CopyableElement, - HeadingElement, - TextElement, -} from '@metamask/snaps-sdk/jsx'; -import { assert, hasProperty } from '@metamask/utils'; -import type { ChangeEvent, FunctionComponent } from 'react'; -import { useState } from 'react'; - -import { BaseNode } from './BaseNode'; -import type { EditableNodeProps } from '../../../types'; -import { getNodeText } from '../utils'; - -export type TextEditableComponent = - | TextElement - | HeadingElement - | CopyableElement; - -export const TEXT_EDITABLE_NODES = ['Heading', 'Text', 'Image', 'Copyable']; - -/** - * An editable node with a text field, which renders an editable component in the builder. - * - * @param props - The props of the component. - * @param props.node - The editable node to render. - * @param props.depth - The depth of the node in the tree. - * @param props.isDragging - Whether the node is being dragged. - * @param props.onChange - A function to call when the node changes. - * @param props.onClose - A function to call when the node is closed. - * @returns An editable node component. - */ -export const TextEditableNode: FunctionComponent< - EditableNodeProps -> = ({ node, depth, isDragging, onChange, onClose }) => { - const text = getNodeText(node); - assert(text !== null, 'Node must have text.'); - const [value, setValue] = useState(text); - - const handleChange = (newValue: ChangeEvent) => { - setValue(newValue.target.value); - onChange?.( - node, - hasProperty(node.data?.props as Record, 'value') - ? 'value' - : 'children', - newValue.target.value, - ); - }; - - return ( - - - - - - ); -}; diff --git a/packages/snaps-simulator/src/features/builder/components/index.ts b/packages/snaps-simulator/src/features/builder/components/index.ts deleted file mode 100644 index 23f287cbaf..0000000000 --- a/packages/snaps-simulator/src/features/builder/components/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './TemplateComponentList'; -export * from './TextEditableNode'; -export * from './Node'; -export * from './NodeRenderer'; -export * from './NodeTree'; diff --git a/packages/snaps-simulator/src/features/builder/index.ts b/packages/snaps-simulator/src/features/builder/index.ts deleted file mode 100644 index d0aefaa611..0000000000 --- a/packages/snaps-simulator/src/features/builder/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './Builder'; diff --git a/packages/snaps-simulator/src/features/builder/utils.test.ts b/packages/snaps-simulator/src/features/builder/utils.test.ts deleted file mode 100644 index da309a21bb..0000000000 --- a/packages/snaps-simulator/src/features/builder/utils.test.ts +++ /dev/null @@ -1,343 +0,0 @@ -import type { JSXElement } from '@metamask/snaps-sdk/jsx'; -import { - Box, - Text, - Form, - Input, - Field, - Button, - Copyable, - Heading, - Option, - Container, -} from '@metamask/snaps-sdk/jsx'; -import type { NodeModel } from '@minoru/react-dnd-treeview'; - -import { - boxToCode, - nodeModelsToComponent, - getNodeText, - isValidBoxChild, - isValidFormChild, - isValidFieldChild, - setElementChildren, - canDropElement, -} from './utils'; - -describe('isValidBoxChild', () => { - it('returns true for valid box children', () => { - const child = Text({ children: 'foo' }); - expect(isValidBoxChild(child)).toBe(true); - }); - - it('returns false for invalid box children', () => { - const child = Container({ children: Input({ name: 'input' }) }); - expect(isValidBoxChild(child)).toBe(false); - }); -}); - -describe('isValidFormChild', () => { - it('returns true for valid form children', () => { - const child = Button({ children: 'foo' }); - expect(isValidFormChild(child)).toBe(true); - }); - - it('returns false for invalid form children', () => { - const child = Option({ children: 'foo', value: 'foo' }); - expect(isValidFormChild(child)).toBe(false); - }); -}); - -describe('isValidFieldChild', () => { - it('returns true for valid field children', () => { - const child = Input({ name: 'input' }); - expect(isValidFieldChild(child)).toBe(true); - }); - - it('returns false for invalid field children', () => { - const child = Option({ children: 'foo', value: 'foo' }); - expect(isValidFieldChild(child)).toBe(false); - }); -}); - -describe('setElementChildren', () => { - it('sets the children of a JSX element', () => { - const element = Box({ children: null }); - const children = Text({ children: 'foo' }); - - const result = setElementChildren(element, children, isValidBoxChild); - expect(result).toStrictEqual(children); - }); - - it('sets the children of a JSX element with a child', () => { - const element = Box({ children: Text({ children: 'foo' }) }); - const children = Text({ children: 'bar' }); - - const result = setElementChildren(element, children, isValidBoxChild); - expect(result).toStrictEqual([element.props.children, children]); - }); - - it('returns the actual children if the child is invalid', () => { - const element = Box({ - children: [Text({ children: 'foo' }), Heading({ children: 'baz' })], - }); - const children = Container({ children: Input({ name: 'input' }) }); - - const result = setElementChildren(element, children, isValidBoxChild); - expect(result).toStrictEqual(element.props.children); - }); -}); - -describe('nodeModelsToComponent', () => { - it('creates a component from an array of node models', () => { - const nodeModels: NodeModel[] = [ - { - id: 1, - parent: 0, - text: 'parent', - data: Box({ children: [] }), - }, - { - id: 2, - parent: 1, - text: 'child', - data: Box({ children: [] }), - }, - { - id: 3, - parent: 2, - text: 'child', - data: Text({ children: 'foo' }), - }, - { - id: 4, - parent: 1, - text: 'child', - data: Form({ name: 'form', children: [] }), - }, - { - id: 5, - parent: 4, - text: 'child', - // @ts-expect-error children is required. - data: Field({ children: [] }), - }, - { - id: 6, - parent: 5, - text: 'child', - data: Input({ name: 'input' }), - }, - ]; - - const component = nodeModelsToComponent(nodeModels); - expect(component).toStrictEqual( - Box({ - children: [ - Box({ children: Text({ children: 'foo' }) }), - Form({ - name: 'form', - children: Field({ children: Input({ name: 'input' }) }), - }), - ], - }), - ); - }); - - it('throws an error if the element type is not supported', () => { - const nodeModels: NodeModel[] = [ - { - id: 1, - parent: 0, - text: 'parent', - data: undefined, - }, - ]; - - expect(() => nodeModelsToComponent(nodeModels)).toThrow( - 'Node model must have data.', - ); - }); - - it('throws an error if the parent node is not found', () => { - const nodeModels: NodeModel[] = [ - { - id: 1, - parent: 2, - text: 'parent', - data: Input({ name: 'input' }), - }, - ]; - - expect(() => nodeModelsToComponent(nodeModels)).toThrow( - 'Root must be a box.', - ); - }); - - it('throws an error if the parent type is not supported', () => { - const nodeModels: NodeModel[] = [ - { - id: 1, - parent: 0, - text: 'parent', - data: Input({ name: 'input' }), - }, - { - id: 2, - parent: 1, - text: 'child', - data: Box({ children: null }), - }, - ]; - - expect(() => nodeModelsToComponent(nodeModels)).toThrow( - 'Parent must be a box, form or field.', - ); - }); -}); - -describe('boxToCode', () => { - it('creates code from a component', () => { - const component = Box({ - children: [ - Text({ children: 'foo' }), - Box({ - children: [Text({ children: 'bar' }), Text({ children: 'baz' })], - }), - ], - }); - - const code = boxToCode(component); - expect(code).toMatchInlineSnapshot(` - "import { Box, Text } from '@metamask/snaps-sdk/jsx'; - - const Component = () => ( - - foo - - bar - baz - - - ); - " - `); - }); - - it('creates code from a component with a form', () => { - const component = Box({ - children: [ - Text({ children: 'foo' }), - Form({ - name: 'form', - children: [ - Field({ - children: [ - Input({ name: 'input' }), - Button({ children: 'button' }), - ], - }), - ], - }), - ], - }); - - const code = boxToCode(component); - expect(code).toMatchInlineSnapshot(` - "import { Box, Button, Field, Form, Input, Text } from '@metamask/snaps-sdk/jsx'; - - const Component = () => ( - - foo -
- - - - -
-
- ); - " - `); - }); -}); - -describe('getNodeText', () => { - it('returns the children of a node model', () => { - const nodeModel: NodeModel = { - id: 1, - parent: 0, - text: 'foo', - data: Text({ children: 'bar' }), - }; - - const nodeText = getNodeText(nodeModel); - expect(nodeText).toBe('bar'); - }); - - it('returns the value of a node model', () => { - const nodeModel: NodeModel = { - id: 1, - parent: 0, - text: 'foo', - data: Copyable({ value: 'bar' }), - }; - - const nodeText = getNodeText(nodeModel); - expect(nodeText).toBe('bar'); - }); - - it('returns null if the node model does not have text', () => { - const nodeModel: NodeModel = { - id: 1, - parent: 0, - text: 'foo', - // @ts-expect-error invalid data. - data: { props: {} }, - }; - - const nodeText = getNodeText(nodeModel); - expect(nodeText).toBeNull(); - }); -}); - -describe('canDropElement', () => { - it('returns true if the element can be dropped in a Box', () => { - const parent = Box({ children: null }); - const child = Text({ children: 'foo' }); - expect(canDropElement(parent, child)).toBe(true); - }); - - it('returns true if the element can be dropped in a Form', () => { - const parent = Form({ - name: 'form', - children: [Button({ children: 'Button' })], - }); - const child = Field({ children: Input({ name: 'Input' }) }); - expect(canDropElement(parent, child)).toBe(true); - }); - - it('returns true if the element can be dropped in a Field', () => { - const parent = Field({ children: Input({ name: 'Input' }) }); - const child = Button({ children: 'Button' }); - expect(canDropElement(parent, child)).toBe(true); - }); - - it('returns false if the element cannot be dropped', () => { - const parent = Text({ children: 'foo' }); - const child = Text({ children: 'bar' }); - expect(canDropElement(parent, child)).toBe(false); - }); - - it('returns false if the parent or child is undefined', () => { - const parent = undefined; - const child = Text({ children: 'foo' }); - - expect(canDropElement(parent, child)).toBe(false); - - const parent2 = Box({ children: null }); - const child2 = undefined; - - expect(canDropElement(parent2, child2)).toBe(false); - }); -}); diff --git a/packages/snaps-simulator/src/features/builder/utils.ts b/packages/snaps-simulator/src/features/builder/utils.ts deleted file mode 100644 index 0b05250e81..0000000000 --- a/packages/snaps-simulator/src/features/builder/utils.ts +++ /dev/null @@ -1,232 +0,0 @@ -import type { - BoxElement, - FieldElement, - FormElement, - JSXElement, -} from '@metamask/snaps-sdk/jsx'; -import { - BoxChildStruct, - FieldChildUnionStruct, - FormChildStruct, - Input, -} from '@metamask/snaps-sdk/jsx'; -import { - deepClone, - getJsxChildren, - hasChildren, - serialiseJsx, -} from '@metamask/snaps-utils'; -import { is } from '@metamask/superstruct'; -import { assert, hasProperty } from '@metamask/utils'; -import type { NodeModel } from '@minoru/react-dnd-treeview'; -import typescript from 'prettier-2/parser-typescript'; -import { format } from 'prettier-2/standalone'; - -/** - * Get the text of a node model. - * - * @param nodeModel - The node model. - * @returns The text of the node model, or `null` if the node model does not - * have text. - */ -export function getNodeText(nodeModel: NodeModel) { - assert(nodeModel.data, 'Node model must have data.'); - - if (hasProperty(nodeModel.data.props, 'value')) { - return nodeModel.data.props.value as string; - } - - if (hasProperty(nodeModel.data.props, 'children')) { - return nodeModel.data.props.children as string; - } - - return null; -} - -/** - * Verify that the node is a valid box children. - * - * @param child - The node to verify. - * @returns True if the node is a valid box children, otherwise false. - */ -export function isValidBoxChild(child: JSXElement) { - return is(child, BoxChildStruct); -} - -/** - * Verify that the node is a valid form children. - * - * @param child - The node to verify. - * @returns True if the node is a valid form children, otherwise false. - */ -export function isValidFormChild(child: JSXElement) { - // Add a children to the Field to pass validation. - const childCopy = deepClone(child); - if (childCopy.type === 'Field') { - childCopy.props.children = Input({ name: 'input' }); - } - return is(childCopy, FormChildStruct); -} - -/** - * Verify that the node is a valid field children. - * - * @param child - The node to verify. - * @returns True if the node is a valid field children, otherwise false. - */ -export function isValidFieldChild(child: JSXElement) { - return is(child, FieldChildUnionStruct); -} -/** - * Set the children of an element. - * - * @param parent - The parent element. - * @param child - The child element. - * @param validator - The validator function. - * @returns The children of the parent element. - */ -export function setElementChildren( - parent: JSXElement, - child: JSXElement, - validator: (child: JSXElement) => boolean, -) { - const actual = getJsxChildren(parent); - - if (!validator(child)) { - return actual; - } - - return actual.length === 0 ? child : [...actual, child]; -} -/** - * Convert an array of node models to a component. This is useful for converting - * the tree view data to a component that can be rendered. - * - * @param nodeModels - The array of node models. - * @returns The component. - */ -export function nodeModelsToComponent( - nodeModels: NodeModel[], -): BoxElement { - // We want to clone the node models so that we don't mutate the original data. - const clonedModels = deepClone(nodeModels); - - for (const nodeModel of clonedModels) { - assert(nodeModel.data, 'Node model must have data.'); - const parent = clonedModels.find((model) => model.id === nodeModel.parent); - if (parent) { - switch (parent.data?.type) { - case 'Box': - parent.data.props.children = setElementChildren( - parent.data, - nodeModel.data, - isValidBoxChild, - ) as BoxElement['props']['children']; - - break; - case 'Form': - parent.data.props.children = setElementChildren( - parent.data, - nodeModel.data, - isValidFormChild, - ) as FormElement['props']['children']; - break; - - case 'Field': - parent.data.props.children = setElementChildren( - parent.data, - nodeModel.data, - isValidFieldChild, - ) as FieldElement['props']['children']; - break; - - default: - throw new Error('Parent must be a box, form or field.'); - } - } - } - - const root = clonedModels.find((model) => model.parent === 0); - - assert(root?.data?.type === 'Box', 'Root must be a box.'); - - return root.data; -} - -/** - * Get all the component types used in a component. - * - * @param component - The component. - * @returns The component types. - */ -function getComponentTypes(component: JSXElement): string[] { - const componentTypes = new Set(); - componentTypes.add(component.type); - - const children = getJsxChildren(component); - - for (const child of children) { - if (typeof child !== 'string') { - componentTypes.add(child.type); - - if (hasChildren(component)) { - const childComponentTypes = getComponentTypes(child); - for (const childComponentType of childComponentTypes) { - componentTypes.add(childComponentType); - } - } - } - } - - return Array.from(componentTypes).sort((a, b) => a.localeCompare(b)); -} - -/** - * Convert a root Box to code. The code is formatted using prettier. - * - * @param component - The root panel. - * @returns The code. - */ -export function boxToCode(component: BoxElement): string { - const types = getComponentTypes(component).join(', '); - - return format( - ` - import { ${types} } from '@metamask/snaps-sdk/jsx'; - - const Component = () => (${serialiseJsx(component)}); -`, - { - parser: 'typescript', - plugins: [typescript], - printWidth: 80, - tabWidth: 2, - singleQuote: true, - trailingComma: 'all', - }, - ); -} - -/** - * Verify that an element can be dropped into a parent element. - * - * @param parent - The parent element. - * @param element - The element to drop. - * @returns True if the element can be dropped, otherwise false. - */ -export function canDropElement(parent?: JSXElement, element?: JSXElement) { - if (!parent || !element) { - return false; - } - - switch (parent.type) { - case 'Box': - return isValidBoxChild(element); - case 'Form': - return isValidFormChild(element); - case 'Field': - return isValidFieldChild(element); - default: - return false; - } -} diff --git a/packages/snaps-simulator/src/features/configuration/Configuration.test.tsx b/packages/snaps-simulator/src/features/configuration/Configuration.test.tsx deleted file mode 100644 index c890ced8a9..0000000000 --- a/packages/snaps-simulator/src/features/configuration/Configuration.test.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { Configuration } from './Configuration'; -import { render } from '../../utils'; - -describe('Configuration', () => { - it('renders', () => { - expect(() => render()).not.toThrow(); - }); -}); diff --git a/packages/snaps-simulator/src/features/configuration/Configuration.tsx b/packages/snaps-simulator/src/features/configuration/Configuration.tsx deleted file mode 100644 index 54a9dbeca2..0000000000 --- a/packages/snaps-simulator/src/features/configuration/Configuration.tsx +++ /dev/null @@ -1,242 +0,0 @@ -import { - Button, - Modal, - ModalContent, - ModalHeader, - ModalBody, - ModalOverlay, - ModalFooter, - FormControl, - FormLabel, - Input, - Switch, - HStack, - Textarea, - Text, - Divider, - InputLeftAddon, - InputRightAddon, - InputGroup, - Select, - useColorMode, -} from '@chakra-ui/react'; -import { - fetchNpmMetadata, - DEFAULT_NPM_REGISTRY, -} from '@metamask/snaps-controllers'; -import { - SnapIdPrefixes, - getSnapPrefix, - stripSnapPrefix, -} from '@metamask/snaps-utils'; -import type { FormEvent } from 'react'; -import { useEffect, useState } from 'react'; - -import { - getOpen, - getSesEnabled, - getSnapId, - getSnapVersion, - getSrp, - setOpen, - setSnapId, - setSnapVersion, -} from './slice'; -import { useDispatch, useSelector } from '../../hooks'; - -export const Configuration = () => { - const dispatch = useDispatch(); - const snapUrl = useSelector(getSnapId); - const snapVersion = useSelector(getSnapVersion); - const srp = useSelector(getSrp); - const sesEnabled = useSelector(getSesEnabled); - const isOpen = useSelector(getOpen); - - const { colorMode, toggleColorMode } = useColorMode(); - - const [snapIdInput, setSnapIdInput] = useState(stripSnapPrefix(snapUrl)); - const [snapIdPrefix, setSnapIdPrefix] = useState( - getSnapPrefix(snapUrl).slice(0, -1), - ); - const [npmVersions, setNpmVersions] = useState([]); - const [selectedNpmVersion, setSelectedNpmVersion] = useState< - string | undefined - >(snapVersion); - - const isNPM = snapIdPrefix === SnapIdPrefixes.npm.slice(0, -1); - - const handleClose = () => { - dispatch(setSnapVersion(selectedNpmVersion)); - dispatch(setSnapId(`${snapIdPrefix}:${snapIdInput}`)); - dispatch(setOpen(false)); - }; - - const handleSnapPrefixChange = (event: FormEvent) => { - setSnapIdPrefix(event.currentTarget.value as SnapIdPrefixes); - }; - - const handleSnapUrlChange = (event: FormEvent) => { - setSnapIdInput(event.currentTarget.value); - }; - - const handleNpmVersionChange = (event: FormEvent) => { - setSelectedNpmVersion(event.currentTarget.value); - }; - - useEffect(() => { - let cancelled = false; - - /** - * Fetches the versions of the NPM snap. - */ - async function fetchNpmVersions() { - const metadata = await fetchNpmMetadata( - snapIdInput, - new URL(DEFAULT_NPM_REGISTRY), - fetch.bind(globalThis), - ); - const versions = Object.keys(metadata.versions).reverse(); - if (!cancelled) { - setNpmVersions(versions); - } - } - - // Reset version state if the inputs are changed - setSelectedNpmVersion(undefined); - setNpmVersions([]); - - // If input is an NPM snap, try to repopulate the version state - if (isNPM) { - fetchNpmVersions().catch((error) => { - // eslint-disable-next-line no-console - console.error(error); - }); - } - - return () => { - cancelled = true; - }; - }, [snapIdInput, snapIdPrefix, isNPM]); - - // const handleSrpChange = (event: FormEvent) => { - // dispatch(setSrp(event.currentTarget.value)); - // }; - // - // const handleSesToggle = () => { - // dispatch(setSesEnabled(!sesEnabled)); - // }; - - const handleDarkModeToggle = () => { - toggleColorMode(); - }; - - return ( - - - - - Configure environment - - Settings and variables to setup the simulation context. - - - - - - Snap location - - - - - - {isNPM && npmVersions.length > 0 && ( - - - - )} - - - Environment SRP -