@metamask/snaps-jest 0.36.0-flask.1 → 0.37.0-flask.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -1
- package/dist/cjs/environment.js.map +1 -1
- package/dist/cjs/internals/interface.js.map +1 -1
- package/dist/cjs/internals/network.js.map +1 -1
- package/dist/cjs/internals/request.js.map +1 -1
- package/dist/cjs/internals/server.js.map +1 -1
- package/dist/cjs/internals/wait-for.js.map +1 -1
- package/dist/cjs/matchers.js.map +1 -1
- package/dist/cjs/options.js.map +1 -1
- package/dist/cjs/types.js.map +1 -1
- package/dist/esm/environment.js.map +1 -1
- package/dist/esm/internals/interface.js.map +1 -1
- package/dist/esm/internals/network.js.map +1 -1
- package/dist/esm/internals/request.js.map +1 -1
- package/dist/esm/internals/server.js.map +1 -1
- package/dist/esm/internals/types.js.map +1 -1
- package/dist/esm/internals/wait-for.js.map +1 -1
- package/dist/esm/matchers.js.map +1 -1
- package/dist/esm/options.js.map +1 -1
- package/dist/esm/types.js.map +1 -1
- package/dist/types/environment.d.ts +1 -1
- package/dist/types/internals/interface.d.ts +2 -2
- package/dist/types/internals/network.d.ts +3 -3
- package/dist/types/internals/request.d.ts +3 -2
- package/dist/types/internals/server.d.ts +2 -2
- package/dist/types/internals/structs.d.ts +4 -0
- package/dist/types/internals/types.d.ts +3 -3
- package/dist/types/internals/wait-for.d.ts +2 -2
- package/dist/types/matchers.d.ts +4 -4
- package/dist/types/options.d.ts +1 -1
- package/dist/types/types.d.ts +6 -6
- package/package.json +12 -11
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.37.0-flask.1]
|
|
10
|
+
### Changed
|
|
11
|
+
- No changes this release.
|
|
12
|
+
|
|
13
|
+
## [0.36.1-flask.1]
|
|
14
|
+
### Changed
|
|
15
|
+
- No changes this release.
|
|
16
|
+
|
|
9
17
|
## [0.36.0-flask.1]
|
|
10
18
|
### Changed
|
|
11
19
|
- Default to newline instead of empty string for network mocking ([#1560](https://github.com/MetaMask/snaps/pull/1560))
|
|
@@ -22,7 +30,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
22
30
|
### Added
|
|
23
31
|
- Initial release ([#1438](https://github.com/MetaMask/snaps/pull/1438), [#1488](https://github.com/MetaMask/snaps/pull/1488), [#1519](https://github.com/MetaMask/snaps/pull/1519), [#1532](https://github.com/MetaMask/snaps/pull/1532))
|
|
24
32
|
|
|
25
|
-
[Unreleased]: https://github.com/MetaMask/snaps/compare/v0.
|
|
33
|
+
[Unreleased]: https://github.com/MetaMask/snaps/compare/v0.37.0-flask.1...HEAD
|
|
34
|
+
[0.37.0-flask.1]: https://github.com/MetaMask/snaps/compare/v0.36.1-flask.1...v0.37.0-flask.1
|
|
35
|
+
[0.36.1-flask.1]: https://github.com/MetaMask/snaps/compare/v0.36.0-flask.1...v0.36.1-flask.1
|
|
26
36
|
[0.36.0-flask.1]: https://github.com/MetaMask/snaps/compare/v0.35.2-flask.1...v0.36.0-flask.1
|
|
27
37
|
[0.35.2-flask.1]: https://github.com/MetaMask/snaps/compare/v0.35.1-flask.1...v0.35.2-flask.1
|
|
28
38
|
[0.35.1-flask.1]: https://github.com/MetaMask/snaps/compare/v0.35.0-flask.1...v0.35.1-flask.1
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/environment.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"sources":["../../src/environment.ts"],"sourcesContent":["import type {\n EnvironmentContext,\n JestEnvironmentConfig,\n} from '@jest/environment';\nimport { assert, createModuleLogger } from '@metamask/utils';\nimport type { Server } from 'http';\nimport NodeEnvironment from 'jest-environment-node';\nimport type { AddressInfo } from 'net';\nimport type { Browser } from 'puppeteer';\nimport { remote } from 'webdriverio';\n\nimport { rootLogger, startServer } from './internals';\nimport type { SnapsEnvironmentOptions } from './options';\nimport { getOptions } from './options';\n\n/* eslint-disable */\ndeclare global {\n const browser: WebdriverIO.Browser;\n const snapsEnvironment: SnapsEnvironment;\n}\n/* eslint-enable */\n\nconst log = createModuleLogger(rootLogger, 'environment');\n\nexport class SnapsEnvironment extends NodeEnvironment {\n // `browser` is always set in the environment setup function. To avoid needing\n // to check for `undefined` everywhere, we use a type assertion here.\n browser!: WebdriverIO.Browser;\n\n #options: SnapsEnvironmentOptions;\n\n #server: Server | undefined;\n\n /**\n * Constructor.\n *\n * @param options - The environment options.\n * @param context - The environment context.\n */\n constructor(options: JestEnvironmentConfig, context: EnvironmentContext) {\n super(options, context);\n this.#options = getOptions(options.projectConfig.testEnvironmentOptions);\n }\n\n /**\n * Set up the environment. This starts the built-in HTTP server, and creates a\n * new browser instance.\n */\n async setup() {\n await super.setup();\n\n if (this.#options.server.enabled) {\n log('Starting server.');\n this.#server = await startServer(this.#options.server);\n }\n\n const args = [];\n if (this.#options.browser.headless) {\n args.push('--headless', '--disable-gpu');\n }\n\n log('Starting browser.');\n this.browser = await remote({\n logLevel: 'error',\n capabilities: {\n browserName: 'chrome',\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'goog:chromeOptions': {\n args,\n },\n },\n });\n\n this.global.browser = this.browser;\n this.global.snapsEnvironment = this;\n }\n\n /**\n * Tear down the environment. This closes the browser, and stops the built-in\n * HTTP server.\n */\n async teardown() {\n if (this.#options.keepAlive) {\n log('Not tearing down environment because keepAlive is enabled.');\n return;\n }\n\n log('Closing browser, and stopping server.');\n await this.browser?.deleteSession();\n this.#server?.close();\n\n await super.teardown();\n }\n\n /**\n * Get the URL to the simulator, including the environment URL.\n *\n * @returns The simulator URL.\n * @throws If the server is not running.\n */\n get url() {\n assert(this.#server, 'Server is not running.');\n\n const { port } = this.#server.address() as AddressInfo;\n const simulatorUrl =\n this.#options.simulatorUrl ?? `http://localhost:${port}/simulator/`;\n\n const executionEnvironmentUrl =\n this.#options.executionEnvironmentUrl ??\n `http://localhost:${port}/environment/`;\n\n return `${simulatorUrl}?environment=${encodeURIComponent(\n executionEnvironmentUrl,\n )}`;\n }\n\n /**\n * Get the snap ID for the current environment, which is used if no snap ID is\n * passed to {@link installSnap}. This assumes that the built-in server is\n * running.\n *\n * @returns The snap ID.\n * @throws If the server is not running.\n */\n get snapId() {\n assert(\n this.#server,\n 'You must specify a snap ID, because the built-in server is not running.',\n );\n\n const { port } = this.#server.address() as AddressInfo;\n return `local:http://localhost:${port}`;\n }\n\n /**\n * Create a new page, and attach logging handlers.\n *\n * @param url - The page URL. Defaults to the specified Snaps Simulator URL,\n * or the default simulator URL if none is specified.\n * @param timeout - The page timeout, in milliseconds.\n * @returns The new page.\n */\n async createPage(url: string = this.url, timeout = 10000) {\n const puppeteer = (await this.browser.getPuppeteer()) as unknown as Browser;\n const page = await puppeteer.newPage();\n\n page.setDefaultTimeout(timeout);\n page.setDefaultNavigationTimeout(timeout);\n\n // Give the page permission to show notifications. This is required for\n // testing `snap_notify`.\n await page.browserContext().overridePermissions(url, ['notifications']);\n\n // `networkidle0` is used to ensure that the page is fully loaded. This\n // makes it wait for no requests to be made, which guarantees that the page\n // is ready.\n await page.goto(url, { waitUntil: 'networkidle0' });\n\n const browserLog = createModuleLogger(rootLogger, 'browser');\n\n page\n // This is fired when the page calls `console.log` or similar.\n .on('console', (message) => {\n browserLog(`[${message.type()}] ${message.text()}`);\n })\n\n // This is fired when the page throws an error.\n .on('pageerror', ({ message }) => {\n browserLog(`[page error] ${message}`);\n });\n\n return page;\n }\n}\n\nexport default SnapsEnvironment;\n"],"names":["SnapsEnvironment","log","createModuleLogger","rootLogger","NodeEnvironment","setup","options","server","enabled","startServer","args","browser","headless","push","remote","logLevel","capabilities","browserName","global","snapsEnvironment","teardown","keepAlive","deleteSession","close","url","assert","port","address","simulatorUrl","executionEnvironmentUrl","encodeURIComponent","snapId","createPage","timeout","puppeteer","getPuppeteer","page","newPage","setDefaultTimeout","setDefaultNavigationTimeout","browserContext","overridePermissions","goto","waitUntil","browserLog","on","message","type","text","constructor","context","getOptions","projectConfig","testEnvironmentOptions"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/internals/interface.ts"],"sourcesContent":["import { DialogType } from '@metamask/rpc-methods';\nimport { assert } from '@metamask/utils';\nimport { Page } from 'puppeteer';\nimport { create } from 'superstruct';\n\nimport { SnapInterface, SnapOptions } from '../types';\nimport { SnapOptionsStruct } from './structs';\nimport { waitFor } from './wait-for';\n\n/**\n * Get the current snap user interface (i.e., dialog). This will throw an error\n * if the snap does not show a user interface within the timeout.\n *\n * @param page - The page to get the interface from.\n * @param options - The options to use.\n * @param options.timeout - The timeout in milliseconds to use. Defaults to\n * `1000`.\n * @returns The user interface object.\n */\nexport async function getInterface(\n page: Page,\n options: SnapOptions = {},\n): Promise<SnapInterface> {\n const { timeout } = create(options, SnapOptionsStruct);\n\n const { type, node: content } = await waitFor(\n async () => {\n const ui = await page.evaluate(() => {\n const state = window.__SIMULATOR_API__.getState();\n return state.simulation.ui;\n });\n\n assert(ui);\n return ui;\n },\n {\n timeout,\n message: 'Timed out waiting for snap interface to be shown.',\n },\n );\n\n switch (type) {\n case DialogType.Alert:\n return {\n type: 'alert',\n content,\n\n ok: async () => {\n await page.evaluate(() => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload: null,\n });\n });\n },\n };\n\n case DialogType.Confirmation:\n return {\n type: 'confirmation',\n content,\n\n ok: async () => {\n await page.evaluate(() => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload: true,\n });\n });\n },\n\n cancel: async () => {\n await page.evaluate(() => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload: false,\n });\n });\n },\n };\n\n case DialogType.Prompt:\n return {\n type: 'prompt',\n content,\n\n ok: async (value) => {\n await page.evaluate((payload) => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload,\n });\n }, value);\n },\n\n cancel: async () => {\n await page.evaluate(() => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload: null,\n });\n });\n },\n };\n\n default:\n throw new Error(`Unknown or unsupported dialog type: ${String(type)}.`);\n }\n}\n\n/**\n * Get the text of the notifications.\n *\n * @param page - The page to get the notifications from.\n * @param requestId - The ID of the request to get the notifications for.\n * @returns The text of the notifications, in order of appearance.\n */\nexport async function getNotifications(page: Page, requestId: string) {\n return await page.evaluate((id) => {\n return window.__SIMULATOR_API__.getNotifications(id);\n }, requestId);\n}\n"],"names":["getInterface","getNotifications","page","options","timeout","create","SnapOptionsStruct","type","node","content","waitFor","ui","evaluate","state","window","__SIMULATOR_API__","getState","simulation","assert","message","DialogType","Alert","ok","dispatch","payload","Confirmation","cancel","Prompt","value","Error","String","requestId","id"],"mappings":";;;;;;;;;;;IAmBsBA,YAAY;eAAZA;;IAkGAC,gBAAgB;eAAhBA;;;4BArHK;uBACJ;6BAEA;yBAGW;yBACV;AAYjB,eAAeD,aACpBE,IAAU,EACVC,UAAuB,CAAC,CAAC;IAEzB,MAAM,EAAEC,OAAO,EAAE,GAAGC,IAAAA,mBAAM,EAACF,SAASG,0BAAiB;IAErD,MAAM,EAAEC,IAAI,EAAEC,MAAMC,OAAO,EAAE,GAAG,MAAMC,IAAAA,gBAAO,EAC3C;QACE,MAAMC,KAAK,MAAMT,KAAKU,QAAQ,CAAC;YAC7B,MAAMC,QAAQC,OAAOC,iBAAiB,CAACC,QAAQ;YAC/C,OAAOH,MAAMI,UAAU,CAACN,EAAE;QAC5B;QAEAO,IAAAA,aAAM,EAACP;QACP,OAAOA;IACT,GACA;QACEP;QACAe,SAAS;IACX;IAGF,OAAQZ;QACN,KAAKa,sBAAU,CAACC,KAAK;YACnB,OAAO;gBACLd,MAAM;gBACNE;gBAEAa,IAAI;oBACF,MAAMpB,KAAKU,QAAQ,CAAC;wBAClBE,OAAOC,iBAAiB,CAACQ,QAAQ,CAAC;4BAChChB,MAAM;4BACNiB,SAAS;wBACX;oBACF;gBACF;YACF;QAEF,KAAKJ,sBAAU,CAACK,YAAY;YAC1B,OAAO;gBACLlB,MAAM;gBACNE;gBAEAa,IAAI;oBACF,MAAMpB,KAAKU,QAAQ,CAAC;wBAClBE,OAAOC,iBAAiB,CAACQ,QAAQ,CAAC;4BAChChB,MAAM;4BACNiB,SAAS;wBACX;oBACF;gBACF;gBAEAE,QAAQ;oBACN,MAAMxB,KAAKU,QAAQ,CAAC;wBAClBE,OAAOC,iBAAiB,CAACQ,QAAQ,CAAC;4BAChChB,MAAM;4BACNiB,SAAS;wBACX;oBACF;gBACF;YACF;QAEF,KAAKJ,sBAAU,CAACO,MAAM;YACpB,OAAO;gBACLpB,MAAM;gBACNE;gBAEAa,IAAI,OAAOM;oBACT,MAAM1B,KAAKU,QAAQ,CAAC,CAACY;wBACnBV,OAAOC,iBAAiB,CAACQ,QAAQ,CAAC;4BAChChB,MAAM;4BACNiB;wBACF;oBACF,GAAGI;gBACL;gBAEAF,QAAQ;oBACN,MAAMxB,KAAKU,QAAQ,CAAC;wBAClBE,OAAOC,iBAAiB,CAACQ,QAAQ,CAAC;4BAChChB,MAAM;4BACNiB,SAAS;wBACX;oBACF;gBACF;YACF;QAEF;YACE,MAAM,IAAIK,MAAM,CAAC,oCAAoC,EAAEC,OAAOvB,MAAM,CAAC,CAAC;IAC1E;AACF;AASO,eAAeN,iBAAiBC,IAAU,EAAE6B,SAAiB;IAClE,OAAO,MAAM7B,KAAKU,QAAQ,CAAC,CAACoB;QAC1B,OAAOlB,OAAOC,iBAAiB,CAACd,gBAAgB,CAAC+B;IACnD,GAAGD;AACL"}
|
|
1
|
+
{"version":3,"sources":["../../../src/internals/interface.ts"],"sourcesContent":["import { DialogType } from '@metamask/rpc-methods';\nimport { assert } from '@metamask/utils';\nimport type { Page } from 'puppeteer';\nimport { create } from 'superstruct';\n\nimport type { SnapInterface, SnapOptions } from '../types';\nimport { SnapOptionsStruct } from './structs';\nimport { waitFor } from './wait-for';\n\n/**\n * Get the current snap user interface (i.e., dialog). This will throw an error\n * if the snap does not show a user interface within the timeout.\n *\n * @param page - The page to get the interface from.\n * @param options - The options to use.\n * @param options.timeout - The timeout in milliseconds to use. Defaults to\n * `1000`.\n * @returns The user interface object.\n */\nexport async function getInterface(\n page: Page,\n options: SnapOptions = {},\n): Promise<SnapInterface> {\n const { timeout } = create(options, SnapOptionsStruct);\n\n const { type, node: content } = await waitFor(\n async () => {\n const ui = await page.evaluate(() => {\n const state = window.__SIMULATOR_API__.getState();\n return state.simulation.ui;\n });\n\n assert(ui);\n return ui;\n },\n {\n timeout,\n message: 'Timed out waiting for snap interface to be shown.',\n },\n );\n\n switch (type) {\n case DialogType.Alert:\n return {\n type: 'alert',\n content,\n\n ok: async () => {\n await page.evaluate(() => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload: null,\n });\n });\n },\n };\n\n case DialogType.Confirmation:\n return {\n type: 'confirmation',\n content,\n\n ok: async () => {\n await page.evaluate(() => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload: true,\n });\n });\n },\n\n cancel: async () => {\n await page.evaluate(() => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload: false,\n });\n });\n },\n };\n\n case DialogType.Prompt:\n return {\n type: 'prompt',\n content,\n\n ok: async (value) => {\n await page.evaluate((payload) => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload,\n });\n }, value);\n },\n\n cancel: async () => {\n await page.evaluate(() => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload: null,\n });\n });\n },\n };\n\n default:\n throw new Error(`Unknown or unsupported dialog type: ${String(type)}.`);\n }\n}\n\n/**\n * Get the text of the notifications.\n *\n * @param page - The page to get the notifications from.\n * @param requestId - The ID of the request to get the notifications for.\n * @returns The text of the notifications, in order of appearance.\n */\nexport async function getNotifications(page: Page, requestId: string) {\n return await page.evaluate((id) => {\n return window.__SIMULATOR_API__.getNotifications(id);\n }, requestId);\n}\n"],"names":["getInterface","getNotifications","page","options","timeout","create","SnapOptionsStruct","type","node","content","waitFor","ui","evaluate","state","window","__SIMULATOR_API__","getState","simulation","assert","message","DialogType","Alert","ok","dispatch","payload","Confirmation","cancel","Prompt","value","Error","String","requestId","id"],"mappings":";;;;;;;;;;;IAmBsBA,YAAY;eAAZA;;IAkGAC,gBAAgB;eAAhBA;;;4BArHK;uBACJ;6BAEA;yBAGW;yBACV;AAYjB,eAAeD,aACpBE,IAAU,EACVC,UAAuB,CAAC,CAAC;IAEzB,MAAM,EAAEC,OAAO,EAAE,GAAGC,IAAAA,mBAAM,EAACF,SAASG,0BAAiB;IAErD,MAAM,EAAEC,IAAI,EAAEC,MAAMC,OAAO,EAAE,GAAG,MAAMC,IAAAA,gBAAO,EAC3C;QACE,MAAMC,KAAK,MAAMT,KAAKU,QAAQ,CAAC;YAC7B,MAAMC,QAAQC,OAAOC,iBAAiB,CAACC,QAAQ;YAC/C,OAAOH,MAAMI,UAAU,CAACN,EAAE;QAC5B;QAEAO,IAAAA,aAAM,EAACP;QACP,OAAOA;IACT,GACA;QACEP;QACAe,SAAS;IACX;IAGF,OAAQZ;QACN,KAAKa,sBAAU,CAACC,KAAK;YACnB,OAAO;gBACLd,MAAM;gBACNE;gBAEAa,IAAI;oBACF,MAAMpB,KAAKU,QAAQ,CAAC;wBAClBE,OAAOC,iBAAiB,CAACQ,QAAQ,CAAC;4BAChChB,MAAM;4BACNiB,SAAS;wBACX;oBACF;gBACF;YACF;QAEF,KAAKJ,sBAAU,CAACK,YAAY;YAC1B,OAAO;gBACLlB,MAAM;gBACNE;gBAEAa,IAAI;oBACF,MAAMpB,KAAKU,QAAQ,CAAC;wBAClBE,OAAOC,iBAAiB,CAACQ,QAAQ,CAAC;4BAChChB,MAAM;4BACNiB,SAAS;wBACX;oBACF;gBACF;gBAEAE,QAAQ;oBACN,MAAMxB,KAAKU,QAAQ,CAAC;wBAClBE,OAAOC,iBAAiB,CAACQ,QAAQ,CAAC;4BAChChB,MAAM;4BACNiB,SAAS;wBACX;oBACF;gBACF;YACF;QAEF,KAAKJ,sBAAU,CAACO,MAAM;YACpB,OAAO;gBACLpB,MAAM;gBACNE;gBAEAa,IAAI,OAAOM;oBACT,MAAM1B,KAAKU,QAAQ,CAAC,CAACY;wBACnBV,OAAOC,iBAAiB,CAACQ,QAAQ,CAAC;4BAChChB,MAAM;4BACNiB;wBACF;oBACF,GAAGI;gBACL;gBAEAF,QAAQ;oBACN,MAAMxB,KAAKU,QAAQ,CAAC;wBAClBE,OAAOC,iBAAiB,CAACQ,QAAQ,CAAC;4BAChChB,MAAM;4BACNiB,SAAS;wBACX;oBACF;gBACF;YACF;QAEF;YACE,MAAM,IAAIK,MAAM,CAAC,oCAAoC,EAAEC,OAAOvB,MAAM,CAAC,CAAC;IAC1E;AACF;AASO,eAAeN,iBAAiBC,IAAU,EAAE6B,SAAiB;IAClE,OAAO,MAAM7B,KAAKU,QAAQ,CAAC,CAACoB;QAC1B,OAAOlB,OAAOC,iBAAiB,CAACd,gBAAgB,CAAC+B;IACnD,GAAGD;AACL"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/internals/network.ts"],"sourcesContent":["import { JSON_RPC_ENDPOINT } from '@metamask/snaps-simulator';\nimport { createModuleLogger, UnsafeJsonStruct } from '@metamask/utils';\nimport { Page, HTTPRequest } from 'puppeteer';\nimport {\n assign,\n boolean,\n create,\n defaulted,\n Infer,\n number,\n object,\n optional,\n record,\n regexp,\n string,\n Struct,\n union,\n unknown,\n func,\n} from 'superstruct';\n\nimport { DeepPartial } from '../types';\nimport { rootLogger } from './logger';\n\n/**\n * The default headers to use for mocked responses. These headers are used to\n * enable CORS.\n */\nconst DEFAULT_HEADERS = {\n /* eslint-disable @typescript-eslint/naming-convention */\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Credentials': 'true',\n 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',\n 'Access-Control-Allow-Headers':\n 'Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers',\n /* eslint-enable @typescript-eslint/naming-convention */\n};\n\nconst log = createModuleLogger(rootLogger, 'network');\n\nexport type Unmock = () => Promise<void>;\n\nexport type Mock = {\n /**\n * A function that can be used to unmock the URL.\n */\n unmock: Unmock;\n};\n\n/**\n * A function that can return `true` if the given request should be mocked, or\n * false if not.\n *\n * @param request - The request to check.\n * @returns Whether to mock the request.\n */\nexport type ConditionFunction = (request: HTTPRequest) => boolean;\n\nconst MockOptionsBaseStruct = object({\n response: defaulted(\n object({\n status: defaulted(number(), 200),\n headers: defaulted(record(string(), unknown()), DEFAULT_HEADERS),\n contentType: defaulted(string(), 'text/plain'),\n\n // Note: We default to a newline here, because the fetch request never\n // resolves if the body is empty.\n body: defaulted(string(), '\\n'),\n }),\n {},\n ),\n});\n\nconst MockOptionsUrlStruct = object({\n url: union([string(), regexp()]),\n partial: optional(boolean()),\n});\n\nconst MockOptionsConditionStruct = object({\n condition: func() as unknown as Struct<ConditionFunction, null>,\n});\n\nexport const MockOptionsStruct = union([\n assign(MockOptionsBaseStruct, MockOptionsUrlStruct),\n assign(MockOptionsBaseStruct, MockOptionsConditionStruct),\n]);\n\n/**\n * The options for the network mocking.\n *\n * @property url - The URL to mock. If a string is provided, the URL will be\n * matched exactly. If a RegExp is provided, the URL will be matched against it.\n * This option is incompatible with the `condition` option.\n * @property partial - If enabled, the request will be mocked if the URL starts\n * with the given URL. This option is ignored if a RegExp is provided to the\n * `url` option. This option is incompatible with the `condition` option.\n * @property condition - A function which gets the {@link HTTPRequest} as\n * parameter and returns a boolean to indicate whether the response should be\n * mocked or not. This option is incompatible with the `url` and `partial`\n * options.\n * @property response - The response to send for the request.\n * @property response.status - The status code to send for the response.\n * Defaults to `200`.\n * @property response.headers - The headers to send for the response. Defaults\n * to headers that enable CORS.\n * @property response.contentType - The content type to send for the response.\n * Defaults to `text/plain`.\n */\nexport type MockOptions = Infer<typeof MockOptionsStruct>;\n\n/**\n * Check if the given URL matches the given request, or if the condition\n * function returns `true`.\n *\n * @param request - The request to check.\n * @param options - The options for the network mocking.\n * @returns Whether the URL matches the request.\n */\nfunction matches(request: HTTPRequest, options: MockOptions) {\n if ('url' in options) {\n const { url, partial } = options;\n if (typeof url === 'string') {\n if (partial) {\n return request.url().startsWith(url);\n }\n\n return url === request.url();\n }\n\n return url.test(request.url());\n }\n\n const { condition } = options;\n return condition(request);\n}\n\n/**\n * Enable network mocking for the given page, and all its sub-frames.\n *\n * @param page - The page to enable network mocking on.\n * @param options - The options for the network mocking.\n * @returns A {@link Mock} object, with an `unmock` function.\n */\nexport async function mock(\n page: Page,\n options: DeepPartial<MockOptions>,\n): Promise<Mock> {\n await page.setRequestInterception(true);\n\n const parsedOptions = create(options, MockOptionsStruct);\n\n /**\n * The mock handler.\n *\n * @param request - The request to handle.\n */\n function handler(request: HTTPRequest) {\n // If the request is already handled, Puppeteer will throw an error if we\n // try to continue the request.\n if (request.isInterceptResolutionHandled()) {\n return;\n }\n\n if (!matches(request, parsedOptions)) {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n request.continue();\n return;\n }\n\n log('Mocking request to %s', request.url());\n\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n request.respond(parsedOptions.response);\n }\n\n /**\n * Unmock the page.\n */\n async function unmock() {\n await page.setRequestInterception(false);\n page.off('request', handler);\n }\n\n page.on('request', handler);\n\n return {\n unmock,\n };\n}\n\nconst MockJsonRpcOptionsStruct = object({\n method: string(),\n result: UnsafeJsonStruct,\n});\n\nexport type MockJsonRpcOptions = Infer<typeof MockJsonRpcOptionsStruct>;\n\n/**\n * Mock an Ethereum JSON-RPC request. This intercepts all requests to the\n * Ethereum provider, and returns the `result` instead.\n *\n * @param page - The page to enable network JSON-RPC mocking on.\n * @param options - The options for the JSON-RPC mock.\n * @param options.method - The JSON-RPC method to mock. Any other methods will be\n * forwarded to the provider.\n * @param options.result - The JSON response to return.\n * @returns A {@link Mock} object, with an `unmock` function.\n */\nexport async function mockJsonRpc(\n page: Page,\n { method, result }: MockJsonRpcOptions,\n) {\n return await mock(page, {\n condition: (request: HTTPRequest) => {\n if (request.url() !== JSON_RPC_ENDPOINT) {\n return false;\n }\n\n const body = request.postData();\n if (!body) {\n return false;\n }\n\n try {\n const json = JSON.parse(body);\n return json.method === method;\n } catch (error) {\n log(\n `Unable to mock \"${method}\" request to Ethereum provider: %s`,\n error.message,\n );\n return false;\n }\n },\n response: {\n status: 200,\n contentType: 'application/json',\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n result,\n }),\n },\n });\n}\n"],"names":["MockOptionsStruct","mock","mockJsonRpc","DEFAULT_HEADERS","log","createModuleLogger","rootLogger","MockOptionsBaseStruct","object","response","defaulted","status","number","headers","record","string","unknown","contentType","body","MockOptionsUrlStruct","url","union","regexp","partial","optional","boolean","MockOptionsConditionStruct","condition","func","assign","matches","request","options","startsWith","test","page","setRequestInterception","parsedOptions","create","handler","isInterceptResolutionHandled","continue","respond","unmock","off","on","MockJsonRpcOptionsStruct","method","result","UnsafeJsonStruct","JSON_RPC_ENDPOINT","postData","json","JSON","parse","error","message","stringify","jsonrpc","id"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/internals/network.ts"],"sourcesContent":["import { JSON_RPC_ENDPOINT } from '@metamask/snaps-simulator';\nimport { createModuleLogger, UnsafeJsonStruct } from '@metamask/utils';\nimport type { Page, HTTPRequest } from 'puppeteer';\nimport type { Infer, Struct } from 'superstruct';\nimport {\n assign,\n boolean,\n create,\n defaulted,\n number,\n object,\n optional,\n record,\n regexp,\n string,\n union,\n unknown,\n func,\n} from 'superstruct';\n\nimport type { DeepPartial } from '../types';\nimport { rootLogger } from './logger';\n\n/**\n * The default headers to use for mocked responses. These headers are used to\n * enable CORS.\n */\nconst DEFAULT_HEADERS = {\n /* eslint-disable @typescript-eslint/naming-convention */\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Credentials': 'true',\n 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',\n 'Access-Control-Allow-Headers':\n 'Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers',\n /* eslint-enable @typescript-eslint/naming-convention */\n};\n\nconst log = createModuleLogger(rootLogger, 'network');\n\nexport type Unmock = () => Promise<void>;\n\nexport type Mock = {\n /**\n * A function that can be used to unmock the URL.\n */\n unmock: Unmock;\n};\n\n/**\n * A function that can return `true` if the given request should be mocked, or\n * false if not.\n *\n * @param request - The request to check.\n * @returns Whether to mock the request.\n */\nexport type ConditionFunction = (request: HTTPRequest) => boolean;\n\nconst MockOptionsBaseStruct = object({\n response: defaulted(\n object({\n status: defaulted(number(), 200),\n headers: defaulted(record(string(), unknown()), DEFAULT_HEADERS),\n contentType: defaulted(string(), 'text/plain'),\n\n // Note: We default to a newline here, because the fetch request never\n // resolves if the body is empty.\n body: defaulted(string(), '\\n'),\n }),\n {},\n ),\n});\n\nconst MockOptionsUrlStruct = object({\n url: union([string(), regexp()]),\n partial: optional(boolean()),\n});\n\nconst MockOptionsConditionStruct = object({\n condition: func() as unknown as Struct<ConditionFunction, null>,\n});\n\nexport const MockOptionsStruct = union([\n assign(MockOptionsBaseStruct, MockOptionsUrlStruct),\n assign(MockOptionsBaseStruct, MockOptionsConditionStruct),\n]);\n\n/**\n * The options for the network mocking.\n *\n * @property url - The URL to mock. If a string is provided, the URL will be\n * matched exactly. If a RegExp is provided, the URL will be matched against it.\n * This option is incompatible with the `condition` option.\n * @property partial - If enabled, the request will be mocked if the URL starts\n * with the given URL. This option is ignored if a RegExp is provided to the\n * `url` option. This option is incompatible with the `condition` option.\n * @property condition - A function which gets the {@link HTTPRequest} as\n * parameter and returns a boolean to indicate whether the response should be\n * mocked or not. This option is incompatible with the `url` and `partial`\n * options.\n * @property response - The response to send for the request.\n * @property response.status - The status code to send for the response.\n * Defaults to `200`.\n * @property response.headers - The headers to send for the response. Defaults\n * to headers that enable CORS.\n * @property response.contentType - The content type to send for the response.\n * Defaults to `text/plain`.\n */\nexport type MockOptions = Infer<typeof MockOptionsStruct>;\n\n/**\n * Check if the given URL matches the given request, or if the condition\n * function returns `true`.\n *\n * @param request - The request to check.\n * @param options - The options for the network mocking.\n * @returns Whether the URL matches the request.\n */\nfunction matches(request: HTTPRequest, options: MockOptions) {\n if ('url' in options) {\n const { url, partial } = options;\n if (typeof url === 'string') {\n if (partial) {\n return request.url().startsWith(url);\n }\n\n return url === request.url();\n }\n\n return url.test(request.url());\n }\n\n const { condition } = options;\n return condition(request);\n}\n\n/**\n * Enable network mocking for the given page, and all its sub-frames.\n *\n * @param page - The page to enable network mocking on.\n * @param options - The options for the network mocking.\n * @returns A {@link Mock} object, with an `unmock` function.\n */\nexport async function mock(\n page: Page,\n options: DeepPartial<MockOptions>,\n): Promise<Mock> {\n await page.setRequestInterception(true);\n\n const parsedOptions = create(options, MockOptionsStruct);\n\n /**\n * The mock handler.\n *\n * @param request - The request to handle.\n */\n function handler(request: HTTPRequest) {\n // If the request is already handled, Puppeteer will throw an error if we\n // try to continue the request.\n if (request.isInterceptResolutionHandled()) {\n return;\n }\n\n if (!matches(request, parsedOptions)) {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n request.continue();\n return;\n }\n\n log('Mocking request to %s', request.url());\n\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n request.respond(parsedOptions.response);\n }\n\n /**\n * Unmock the page.\n */\n async function unmock() {\n await page.setRequestInterception(false);\n page.off('request', handler);\n }\n\n page.on('request', handler);\n\n return {\n unmock,\n };\n}\n\nconst MockJsonRpcOptionsStruct = object({\n method: string(),\n result: UnsafeJsonStruct,\n});\n\nexport type MockJsonRpcOptions = Infer<typeof MockJsonRpcOptionsStruct>;\n\n/**\n * Mock an Ethereum JSON-RPC request. This intercepts all requests to the\n * Ethereum provider, and returns the `result` instead.\n *\n * @param page - The page to enable network JSON-RPC mocking on.\n * @param options - The options for the JSON-RPC mock.\n * @param options.method - The JSON-RPC method to mock. Any other methods will be\n * forwarded to the provider.\n * @param options.result - The JSON response to return.\n * @returns A {@link Mock} object, with an `unmock` function.\n */\nexport async function mockJsonRpc(\n page: Page,\n { method, result }: MockJsonRpcOptions,\n) {\n return await mock(page, {\n condition: (request: HTTPRequest) => {\n if (request.url() !== JSON_RPC_ENDPOINT) {\n return false;\n }\n\n const body = request.postData();\n if (!body) {\n return false;\n }\n\n try {\n const json = JSON.parse(body);\n return json.method === method;\n } catch (error) {\n log(\n `Unable to mock \"${method}\" request to Ethereum provider: %s`,\n error.message,\n );\n return false;\n }\n },\n response: {\n status: 200,\n contentType: 'application/json',\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n result,\n }),\n },\n });\n}\n"],"names":["MockOptionsStruct","mock","mockJsonRpc","DEFAULT_HEADERS","log","createModuleLogger","rootLogger","MockOptionsBaseStruct","object","response","defaulted","status","number","headers","record","string","unknown","contentType","body","MockOptionsUrlStruct","url","union","regexp","partial","optional","boolean","MockOptionsConditionStruct","condition","func","assign","matches","request","options","startsWith","test","page","setRequestInterception","parsedOptions","create","handler","isInterceptResolutionHandled","continue","respond","unmock","off","on","MockJsonRpcOptionsStruct","method","result","UnsafeJsonStruct","JSON_RPC_ENDPOINT","postData","json","JSON","parse","error","message","stringify","jsonrpc","id"],"mappings":";;;;;;;;;;;IAiFaA,iBAAiB;eAAjBA;;IA6DSC,IAAI;eAAJA;;IAiEAC,WAAW;eAAXA;;;gCA/MY;uBACmB;6BAiB9C;wBAGoB;AAE3B;;;CAGC,GACD,MAAMC,kBAAkB;IACtB,uDAAuD,GACvD,+BAA+B;IAC/B,oCAAoC;IACpC,gCAAgC;IAChC,gCACE;AAEJ;AAEA,MAAMC,MAAMC,IAAAA,yBAAkB,EAACC,kBAAU,EAAE;AAoB3C,MAAMC,wBAAwBC,IAAAA,mBAAM,EAAC;IACnCC,UAAUC,IAAAA,sBAAS,EACjBF,IAAAA,mBAAM,EAAC;QACLG,QAAQD,IAAAA,sBAAS,EAACE,IAAAA,mBAAM,KAAI;QAC5BC,SAASH,IAAAA,sBAAS,EAACI,IAAAA,mBAAM,EAACC,IAAAA,mBAAM,KAAIC,IAAAA,oBAAO,MAAKb;QAChDc,aAAaP,IAAAA,sBAAS,EAACK,IAAAA,mBAAM,KAAI;QAEjC,sEAAsE;QACtE,iCAAiC;QACjCG,MAAMR,IAAAA,sBAAS,EAACK,IAAAA,mBAAM,KAAI;IAC5B,IACA,CAAC;AAEL;AAEA,MAAMI,uBAAuBX,IAAAA,mBAAM,EAAC;IAClCY,KAAKC,IAAAA,kBAAK,EAAC;QAACN,IAAAA,mBAAM;QAAIO,IAAAA,mBAAM;KAAG;IAC/BC,SAASC,IAAAA,qBAAQ,EAACC,IAAAA,oBAAO;AAC3B;AAEA,MAAMC,6BAA6BlB,IAAAA,mBAAM,EAAC;IACxCmB,WAAWC,IAAAA,iBAAI;AACjB;AAEO,MAAM5B,oBAAoBqB,IAAAA,kBAAK,EAAC;IACrCQ,IAAAA,mBAAM,EAACtB,uBAAuBY;IAC9BU,IAAAA,mBAAM,EAACtB,uBAAuBmB;CAC/B;AAyBD;;;;;;;CAOC,GACD,SAASI,QAAQC,OAAoB,EAAEC,OAAoB;IACzD,IAAI,SAASA,SAAS;QACpB,MAAM,EAAEZ,GAAG,EAAEG,OAAO,EAAE,GAAGS;QACzB,IAAI,OAAOZ,QAAQ,UAAU;YAC3B,IAAIG,SAAS;gBACX,OAAOQ,QAAQX,GAAG,GAAGa,UAAU,CAACb;YAClC;YAEA,OAAOA,QAAQW,QAAQX,GAAG;QAC5B;QAEA,OAAOA,IAAIc,IAAI,CAACH,QAAQX,GAAG;IAC7B;IAEA,MAAM,EAAEO,SAAS,EAAE,GAAGK;IACtB,OAAOL,UAAUI;AACnB;AASO,eAAe9B,KACpBkC,IAAU,EACVH,OAAiC;IAEjC,MAAMG,KAAKC,sBAAsB,CAAC;IAElC,MAAMC,gBAAgBC,IAAAA,mBAAM,EAACN,SAAShC;IAEtC;;;;GAIC,GACD,SAASuC,QAAQR,OAAoB;QACnC,yEAAyE;QACzE,+BAA+B;QAC/B,IAAIA,QAAQS,4BAA4B,IAAI;YAC1C;QACF;QAEA,IAAI,CAACV,QAAQC,SAASM,gBAAgB;YACpC,mEAAmE;YACnEN,QAAQU,QAAQ;YAChB;QACF;QAEArC,IAAI,yBAAyB2B,QAAQX,GAAG;QAExC,mEAAmE;QACnEW,QAAQW,OAAO,CAACL,cAAc5B,QAAQ;IACxC;IAEA;;GAEC,GACD,eAAekC;QACb,MAAMR,KAAKC,sBAAsB,CAAC;QAClCD,KAAKS,GAAG,CAAC,WAAWL;IACtB;IAEAJ,KAAKU,EAAE,CAAC,WAAWN;IAEnB,OAAO;QACLI;IACF;AACF;AAEA,MAAMG,2BAA2BtC,IAAAA,mBAAM,EAAC;IACtCuC,QAAQhC,IAAAA,mBAAM;IACdiC,QAAQC,uBAAgB;AAC1B;AAeO,eAAe/C,YACpBiC,IAAU,EACV,EAAEY,MAAM,EAAEC,MAAM,EAAsB;IAEtC,OAAO,MAAM/C,KAAKkC,MAAM;QACtBR,WAAW,CAACI;YACV,IAAIA,QAAQX,GAAG,OAAO8B,iCAAiB,EAAE;gBACvC,OAAO;YACT;YAEA,MAAMhC,OAAOa,QAAQoB,QAAQ;YAC7B,IAAI,CAACjC,MAAM;gBACT,OAAO;YACT;YAEA,IAAI;gBACF,MAAMkC,OAAOC,KAAKC,KAAK,CAACpC;gBACxB,OAAOkC,KAAKL,MAAM,KAAKA;YACzB,EAAE,OAAOQ,OAAO;gBACdnD,IACE,CAAC,gBAAgB,EAAE2C,OAAO,kCAAkC,CAAC,EAC7DQ,MAAMC,OAAO;gBAEf,OAAO;YACT;QACF;QACA/C,UAAU;YACRE,QAAQ;YACRM,aAAa;YACbC,MAAMmC,KAAKI,SAAS,CAAC;gBACnBC,SAAS;gBACTC,IAAI;gBACJX;YACF;QACF;IACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/internals/request.ts"],"sourcesContent":["import { Component } from '@metamask/snaps-ui';\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/internals/request.ts"],"sourcesContent":["import type { Component } from '@metamask/snaps-ui';\nimport type { SnapRpcHookArgs } from '@metamask/snaps-utils';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport {\n assert,\n createModuleLogger,\n hasProperty,\n isPlainObject,\n} from '@metamask/utils';\nimport { getDocument, queries } from 'pptr-testing-library';\nimport type { Page } from 'puppeteer';\nimport { create } from 'superstruct';\n\nimport type {\n CronjobOptions,\n RequestOptions,\n SnapRequest,\n SnapResponse,\n TransactionOptions,\n} from '../types';\nimport { getInterface, getNotifications } from './interface';\nimport { rootLogger } from './logger';\nimport { TransactionOptionsStruct } from './structs';\nimport { waitForResponse } from './wait-for';\n\nconst log = createModuleLogger(rootLogger, 'request');\n\n/**\n * Send a request to the snap.\n *\n * @param page - The page to send the request from.\n * @param args - The request arguments.\n * @returns The request ID.\n */\nasync function sendRequest(page: Page, args: SnapRpcHookArgs) {\n const document = await getDocument(page);\n const button = await queries.getByTestId(\n document,\n `navigation-${args.handler}`,\n );\n\n // Navigate to the request handler page.\n await button.click();\n\n return await page.evaluate((payload) => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/sendRequest',\n payload,\n });\n\n return window.__SIMULATOR_API__.getRequestId();\n }, args);\n}\n\n/**\n * Send a request to the snap.\n *\n * @param page - The page to send the request from.\n * @param options - The request options.\n * @param options.origin - The origin of the request. Defaults to `metamask.io`.\n * @param handler - The handler to use. Defaults to `onRpcRequest`.\n * @returns The response.\n */\nexport function request(\n page: Page,\n { origin = 'metamask.io', ...options }: RequestOptions,\n handler:\n | HandlerType.OnRpcRequest\n | HandlerType.OnCronjob = HandlerType.OnRpcRequest,\n) {\n const doRequest = async (): Promise<SnapResponse> => {\n const args: SnapRpcHookArgs = {\n origin,\n handler,\n request: {\n jsonrpc: '2.0',\n id: 1,\n ...options,\n },\n };\n\n log('Sending request %o', args);\n\n const promise = waitForResponse(page, handler);\n const id = await sendRequest(page, args);\n const response = await promise;\n\n log('Received response %o', response);\n\n const notifications = await getNotifications(page, id);\n\n return { id, response, notifications };\n };\n\n // This is a bit hacky, but it allows us to add the `getInterface` method\n // to the response promise.\n const response = doRequest() as SnapRequest;\n\n response.getInterface = async (getInterfaceOptions) => {\n return await getInterface(page, getInterfaceOptions);\n };\n\n return response;\n}\n\n/**\n * Send a transaction to the snap.\n *\n * @param page - The page to send the transaction from.\n * @param options - The transaction options.\n * @returns The response.\n */\nexport async function sendTransaction(\n page: Page,\n options: Partial<TransactionOptions>,\n) {\n const {\n origin: transactionOrigin,\n chainId,\n ...transaction\n } = create(options, TransactionOptionsStruct);\n\n const args: SnapRpcHookArgs = {\n origin: '',\n handler: HandlerType.OnTransaction,\n request: {\n jsonrpc: '2.0',\n method: '',\n params: {\n chainId,\n transaction,\n transactionOrigin,\n },\n },\n };\n\n log('Sending transaction %o', args);\n\n const promise = waitForResponse(page, HandlerType.OnTransaction);\n const id = await sendRequest(page, args);\n const response = await promise;\n\n log('Received response %o', response);\n\n if (hasProperty(response, 'error')) {\n return { id, response, notifications: [] };\n }\n\n assert(isPlainObject(response.result));\n assert(hasProperty(response.result, 'content'));\n\n return {\n id,\n response,\n notifications: [],\n content: response.result.content as Component,\n };\n}\n\n/**\n * Run a cronjob.\n *\n * @param page - The page to run the cronjob from.\n * @param options - The request options.\n * @returns The response.\n */\nexport function runCronjob(page: Page, options: CronjobOptions) {\n return request(page, options, HandlerType.OnCronjob);\n}\n"],"names":["request","sendTransaction","runCronjob","log","createModuleLogger","rootLogger","sendRequest","page","args","document","getDocument","button","queries","getByTestId","handler","click","evaluate","payload","window","__SIMULATOR_API__","dispatch","type","getRequestId","origin","options","HandlerType","OnRpcRequest","doRequest","jsonrpc","id","promise","waitForResponse","response","notifications","getNotifications","getInterface","getInterfaceOptions","transactionOrigin","chainId","transaction","create","TransactionOptionsStruct","OnTransaction","method","params","hasProperty","assert","isPlainObject","result","content","OnCronjob"],"mappings":";;;;;;;;;;;IA+DgBA,OAAO;eAAPA;;IAiDMC,eAAe;eAAfA;;IAsDNC,UAAU;eAAVA;;;4BApKY;uBAMrB;oCAC8B;6BAEd;2BASwB;wBACpB;yBACc;yBACT;AAEhC,MAAMC,MAAMC,IAAAA,yBAAkB,EAACC,kBAAU,EAAE;AAE3C;;;;;;CAMC,GACD,eAAeC,YAAYC,IAAU,EAAEC,IAAqB;IAC1D,MAAMC,WAAW,MAAMC,IAAAA,+BAAW,EAACH;IACnC,MAAMI,SAAS,MAAMC,2BAAO,CAACC,WAAW,CACtCJ,UACA,CAAC,WAAW,EAAED,KAAKM,OAAO,CAAC,CAAC;IAG9B,wCAAwC;IACxC,MAAMH,OAAOI,KAAK;IAElB,OAAO,MAAMR,KAAKS,QAAQ,CAAC,CAACC;QAC1BC,OAAOC,iBAAiB,CAACC,QAAQ,CAAC;YAChCC,MAAM;YACNJ;QACF;QAEA,OAAOC,OAAOC,iBAAiB,CAACG,YAAY;IAC9C,GAAGd;AACL;AAWO,SAASR,QACdO,IAAU,EACV,EAAEgB,SAAS,aAAa,EAAE,GAAGC,SAAyB,EACtDV,UAE4BW,uBAAW,CAACC,YAAY;IAEpD,MAAMC,YAAY;QAChB,MAAMnB,OAAwB;YAC5Be;YACAT;YACAd,SAAS;gBACP4B,SAAS;gBACTC,IAAI;gBACJ,GAAGL,OAAO;YACZ;QACF;QAEArB,IAAI,sBAAsBK;QAE1B,MAAMsB,UAAUC,IAAAA,wBAAe,EAACxB,MAAMO;QACtC,MAAMe,KAAK,MAAMvB,YAAYC,MAAMC;QACnC,MAAMwB,WAAW,MAAMF;QAEvB3B,IAAI,wBAAwB6B;QAE5B,MAAMC,gBAAgB,MAAMC,IAAAA,2BAAgB,EAAC3B,MAAMsB;QAEnD,OAAO;YAAEA;YAAIG;YAAUC;QAAc;IACvC;IAEA,yEAAyE;IACzE,2BAA2B;IAC3B,MAAMD,WAAWL;IAEjBK,SAASG,YAAY,GAAG,OAAOC;QAC7B,OAAO,MAAMD,IAAAA,uBAAY,EAAC5B,MAAM6B;IAClC;IAEA,OAAOJ;AACT;AASO,eAAe/B,gBACpBM,IAAU,EACViB,OAAoC;IAEpC,MAAM,EACJD,QAAQc,iBAAiB,EACzBC,OAAO,EACP,GAAGC,aACJ,GAAGC,IAAAA,mBAAM,EAAChB,SAASiB,iCAAwB;IAE5C,MAAMjC,OAAwB;QAC5Be,QAAQ;QACRT,SAASW,uBAAW,CAACiB,aAAa;QAClC1C,SAAS;YACP4B,SAAS;YACTe,QAAQ;YACRC,QAAQ;gBACNN;gBACAC;gBACAF;YACF;QACF;IACF;IAEAlC,IAAI,0BAA0BK;IAE9B,MAAMsB,UAAUC,IAAAA,wBAAe,EAACxB,MAAMkB,uBAAW,CAACiB,aAAa;IAC/D,MAAMb,KAAK,MAAMvB,YAAYC,MAAMC;IACnC,MAAMwB,WAAW,MAAMF;IAEvB3B,IAAI,wBAAwB6B;IAE5B,IAAIa,IAAAA,kBAAW,EAACb,UAAU,UAAU;QAClC,OAAO;YAAEH;YAAIG;YAAUC,eAAe,EAAE;QAAC;IAC3C;IAEAa,IAAAA,aAAM,EAACC,IAAAA,oBAAa,EAACf,SAASgB,MAAM;IACpCF,IAAAA,aAAM,EAACD,IAAAA,kBAAW,EAACb,SAASgB,MAAM,EAAE;IAEpC,OAAO;QACLnB;QACAG;QACAC,eAAe,EAAE;QACjBgB,SAASjB,SAASgB,MAAM,CAACC,OAAO;IAClC;AACF;AASO,SAAS/C,WAAWK,IAAU,EAAEiB,OAAuB;IAC5D,OAAOxB,QAAQO,MAAMiB,SAASC,uBAAW,CAACyB,SAAS;AACrD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/internals/server.ts"],"sourcesContent":["import {\n assertIsSnapManifest,\n isDirectory,\n isFile,\n
|
|
1
|
+
{"version":3,"sources":["../../../src/internals/server.ts"],"sourcesContent":["import type { SnapManifest } from '@metamask/snaps-utils';\nimport {\n assertIsSnapManifest,\n isDirectory,\n isFile,\n} from '@metamask/snaps-utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport express from 'express';\nimport { promises as fs } from 'fs';\nimport type { Server } from 'http';\nimport { createServer } from 'http';\nimport { resolve as pathResolve, dirname } from 'path';\n\nimport type { SnapsEnvironmentOptions } from '../options';\nimport { rootLogger } from './logger';\n\nconst SNAPS_EXECUTION_ENVIRONMENTS_PATH = pathResolve(\n dirname(\n require.resolve('@metamask/snaps-execution-environments/package.json'),\n ),\n 'dist',\n 'browserify',\n 'iframe',\n);\n\nconst SNAPS_SIMULATOR_PATH = pathResolve(\n dirname(require.resolve('@metamask/snaps-simulator/package.json')),\n 'dist',\n 'webpack',\n 'test',\n);\n\nexport type ServerOptions = Required<\n // We need a double `Required` for the type to be inferred correctly.\n Required<SnapsEnvironmentOptions>['server']\n>;\n\n/**\n * Check that:\n *\n * - The root directory exists.\n * - The root directory contains a `snap.manifest.json` file.\n * - The file path in the manifest exists.\n *\n * @param root - The root directory.\n * @throws If any of the checks fail.\n */\nasync function assertRoot(root: string) {\n if (!root) {\n throw new Error('You must specify a root directory.');\n }\n\n if (!(await isDirectory(root, false))) {\n throw new Error(`Root directory \"${root}\" is not a directory.`);\n }\n\n const manifestPath = pathResolve(root, 'snap.manifest.json');\n const manifest: SnapManifest = await fs\n .readFile(manifestPath, 'utf8')\n .then(JSON.parse);\n\n assertIsSnapManifest(manifest);\n const filePath = pathResolve(root, manifest.source.location.npm.filePath);\n\n if (!(await isFile(filePath))) {\n throw new Error(\n `File \"${filePath}\" does not exist, or is not a file. Did you forget to build your snap?`,\n );\n }\n}\n\n/**\n * Start an HTTP server on `localhost` with a random port. This is used to serve\n * the static files for the environment.\n *\n * @param options - The options to use.\n * @param options.port - The port to use for the server.\n * @param options.root - The root directory to serve from the server.\n * @returns The HTTP server.\n */\nexport async function startServer(options: ServerOptions) {\n await assertRoot(options.root);\n\n const log = createModuleLogger(rootLogger, 'server');\n const app = express();\n\n app.use((_request, response, next) => {\n response.header('Access-Control-Allow-Origin', '*');\n response.header('Access-Control-Allow-Credentials', 'true');\n response.header('Access-Control-Allow-Methods', 'GET, OPTIONS');\n response.header('Access-Control-Allow-Headers', 'Content-Type');\n\n next();\n });\n\n app.use('/environment', express.static(SNAPS_EXECUTION_ENVIRONMENTS_PATH));\n app.use('/simulator', express.static(SNAPS_SIMULATOR_PATH));\n app.use(express.static(pathResolve(process.cwd(), options.root)));\n\n const server = createServer(app);\n return await new Promise<Server>((resolve, reject) => {\n server.listen(options.port, () => {\n resolve(server);\n });\n\n server.on('error', (error) => {\n log(error);\n reject(error);\n });\n });\n}\n"],"names":["startServer","SNAPS_EXECUTION_ENVIRONMENTS_PATH","pathResolve","dirname","require","resolve","SNAPS_SIMULATOR_PATH","assertRoot","root","Error","isDirectory","manifestPath","manifest","fs","readFile","then","JSON","parse","assertIsSnapManifest","filePath","source","location","npm","isFile","options","log","createModuleLogger","rootLogger","app","express","use","_request","response","next","header","static","process","cwd","server","createServer","Promise","reject","listen","port","on","error"],"mappings":";;;;+BAgFsBA;;;eAAAA;;;4BA3Ef;uBAC4B;gEACf;oBACW;sBAEF;sBACmB;wBAGrB;;;;;;AAE3B,MAAMC,oCAAoCC,IAAAA,aAAW,EACnDC,IAAAA,aAAO,EACLC,QAAQC,OAAO,CAAC,yDAElB,QACA,cACA;AAGF,MAAMC,uBAAuBJ,IAAAA,aAAW,EACtCC,IAAAA,aAAO,EAACC,QAAQC,OAAO,CAAC,4CACxB,QACA,WACA;AAQF;;;;;;;;;CASC,GACD,eAAeE,WAAWC,IAAY;IACpC,IAAI,CAACA,MAAM;QACT,MAAM,IAAIC,MAAM;IAClB;IAEA,IAAI,CAAE,MAAMC,IAAAA,uBAAW,EAACF,MAAM,QAAS;QACrC,MAAM,IAAIC,MAAM,CAAC,gBAAgB,EAAED,KAAK,qBAAqB,CAAC;IAChE;IAEA,MAAMG,eAAeT,IAAAA,aAAW,EAACM,MAAM;IACvC,MAAMI,WAAyB,MAAMC,YAAE,CACpCC,QAAQ,CAACH,cAAc,QACvBI,IAAI,CAACC,KAAKC,KAAK;IAElBC,IAAAA,gCAAoB,EAACN;IACrB,MAAMO,WAAWjB,IAAAA,aAAW,EAACM,MAAMI,SAASQ,MAAM,CAACC,QAAQ,CAACC,GAAG,CAACH,QAAQ;IAExE,IAAI,CAAE,MAAMI,IAAAA,kBAAM,EAACJ,WAAY;QAC7B,MAAM,IAAIV,MACR,CAAC,MAAM,EAAEU,SAAS,sEAAsE,CAAC;IAE7F;AACF;AAWO,eAAenB,YAAYwB,OAAsB;IACtD,MAAMjB,WAAWiB,QAAQhB,IAAI;IAE7B,MAAMiB,MAAMC,IAAAA,yBAAkB,EAACC,kBAAU,EAAE;IAC3C,MAAMC,MAAMC,IAAAA,gBAAO;IAEnBD,IAAIE,GAAG,CAAC,CAACC,UAAUC,UAAUC;QAC3BD,SAASE,MAAM,CAAC,+BAA+B;QAC/CF,SAASE,MAAM,CAAC,oCAAoC;QACpDF,SAASE,MAAM,CAAC,gCAAgC;QAChDF,SAASE,MAAM,CAAC,gCAAgC;QAEhDD;IACF;IAEAL,IAAIE,GAAG,CAAC,gBAAgBD,gBAAO,CAACM,MAAM,CAAClC;IACvC2B,IAAIE,GAAG,CAAC,cAAcD,gBAAO,CAACM,MAAM,CAAC7B;IACrCsB,IAAIE,GAAG,CAACD,gBAAO,CAACM,MAAM,CAACjC,IAAAA,aAAW,EAACkC,QAAQC,GAAG,IAAIb,QAAQhB,IAAI;IAE9D,MAAM8B,SAASC,IAAAA,kBAAY,EAACX;IAC5B,OAAO,MAAM,IAAIY,QAAgB,CAACnC,SAASoC;QACzCH,OAAOI,MAAM,CAAClB,QAAQmB,IAAI,EAAE;YAC1BtC,QAAQiC;QACV;QAEAA,OAAOM,EAAE,CAAC,SAAS,CAACC;YAClBpB,IAAIoB;YACJJ,OAAOI;QACT;IACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/internals/wait-for.ts"],"sourcesContent":["import { HandlerType } from '@metamask/snaps-utils';\nimport { assert, createModuleLogger } from '@metamask/utils';\nimport { waitFor as waitForPuppeteer } from 'pptr-testing-library';\nimport { Page } from 'puppeteer';\n\nimport { SnapResponse } from '../types';\nimport { rootLogger } from './logger';\n\nexport type WaitForOptions = {\n /**\n * The timeout in milliseconds.\n */\n timeout?: number;\n\n /**\n * The error message to throw if the condition is not met.\n */\n message?: string;\n};\n\nconst log = createModuleLogger(rootLogger, 'wait-for');\n\n/**\n * Wait for a condition to be true. This is a wrapper around\n * `pptr-testing-library`'s `waitFor` function, with the addition of a custom\n * error message.\n *\n * @param fn - The condition to wait for.\n * @param options - The options.\n * @param options.timeout - The timeout in milliseconds.\n * @param options.message - The error message to throw if the condition is not\n * met.\n * @returns A promise that resolves when the condition is met. The promise\n * resolves to the return value of the condition function.\n */\nexport async function waitFor<Result>(\n fn: () => Promise<Result>,\n { timeout = 3000, message }: WaitForOptions = {},\n) {\n try {\n let result: Result | undefined;\n\n await waitForPuppeteer(\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async () => {\n // Puppeteer's `waitFor` function does not support returning a value\n // from the condition function, so we need to use a variable outside\n // the scope of the function.\n result = await fn();\n },\n {\n timeout,\n },\n );\n\n assert(result !== undefined);\n return result;\n } catch (error) {\n if (message) {\n throw new Error(message);\n }\n\n throw error;\n }\n}\n\n/**\n * Wait for a JSON-RPC response.\n *\n * @param page - The page to wait for the response on.\n * @param type - The type of response to wait for.\n * @returns The JSON-RPC response.\n */\nexport async function waitForResponse(\n page: Page,\n type:\n | HandlerType.OnTransaction\n | HandlerType.OnRpcRequest\n | HandlerType.OnCronjob,\n) {\n log('Waiting for response of type %s.', type);\n\n return await page.evaluate(async (_type) => {\n return new Promise<SnapResponse['response']>((resolve) => {\n window.__SIMULATOR_API__.dispatch({\n type: `${_type}/clearResponse`,\n });\n\n const unsubscribe = window.__SIMULATOR_API__.subscribe(() => {\n const state = window.__SIMULATOR_API__.getState();\n const { pending, response } = state[_type];\n\n if (!pending && response) {\n unsubscribe();\n\n resolve(response);\n }\n });\n });\n }, type);\n}\n"],"names":["waitFor","waitForResponse","log","createModuleLogger","rootLogger","fn","timeout","message","result","waitForPuppeteer","assert","undefined","error","Error","page","type","evaluate","_type","Promise","resolve","window","__SIMULATOR_API__","dispatch","unsubscribe","subscribe","state","getState","pending","response"],"mappings":";;;;;;;;;;;IAmCsBA,OAAO;eAAPA;;IAsCAC,eAAe;eAAfA;;;uBAxEqB;oCACC;wBAIjB;AAc3B,MAAMC,MAAMC,IAAAA,yBAAkB,EAACC,kBAAU,EAAE;AAepC,eAAeJ,QACpBK,EAAyB,EACzB,EAAEC,UAAU,IAAI,EAAEC,OAAO,EAAkB,GAAG,CAAC,CAAC;IAEhD,IAAI;QACF,IAAIC;QAEJ,MAAMC,IAAAA,2BAAgB,EACpB,kEAAkE;QAClE;YACE,oEAAoE;YACpE,oEAAoE;YACpE,6BAA6B;YAC7BD,SAAS,MAAMH;QACjB,GACA;YACEC;QACF;QAGFI,IAAAA,aAAM,EAACF,WAAWG;QAClB,OAAOH;IACT,EAAE,OAAOI,OAAO;QACd,IAAIL,SAAS;YACX,MAAM,IAAIM,MAAMN;QAClB;QAEA,MAAMK;IACR;AACF;AASO,eAAeX,gBACpBa,IAAU,EACVC,IAGyB;IAEzBb,IAAI,oCAAoCa;IAExC,OAAO,MAAMD,KAAKE,QAAQ,CAAC,OAAOC;QAChC,OAAO,IAAIC,QAAkC,CAACC;YAC5CC,OAAOC,iBAAiB,CAACC,QAAQ,CAAC;gBAChCP,MAAM,CAAC,EAAEE,MAAM,cAAc,CAAC;YAChC;YAEA,MAAMM,cAAcH,OAAOC,iBAAiB,CAACG,SAAS,CAAC;gBACrD,MAAMC,QAAQL,OAAOC,iBAAiB,CAACK,QAAQ;gBAC/C,MAAM,EAAEC,OAAO,EAAEC,QAAQ,EAAE,GAAGH,KAAK,CAACR,MAAM;gBAE1C,IAAI,CAACU,WAAWC,UAAU;oBACxBL;oBAEAJ,QAAQS;gBACV;YACF;QACF;IACF,GAAGb;AACL"}
|
|
1
|
+
{"version":3,"sources":["../../../src/internals/wait-for.ts"],"sourcesContent":["import type { HandlerType } from '@metamask/snaps-utils';\nimport { assert, createModuleLogger } from '@metamask/utils';\nimport { waitFor as waitForPuppeteer } from 'pptr-testing-library';\nimport type { Page } from 'puppeteer';\n\nimport type { SnapResponse } from '../types';\nimport { rootLogger } from './logger';\n\nexport type WaitForOptions = {\n /**\n * The timeout in milliseconds.\n */\n timeout?: number;\n\n /**\n * The error message to throw if the condition is not met.\n */\n message?: string;\n};\n\nconst log = createModuleLogger(rootLogger, 'wait-for');\n\n/**\n * Wait for a condition to be true. This is a wrapper around\n * `pptr-testing-library`'s `waitFor` function, with the addition of a custom\n * error message.\n *\n * @param fn - The condition to wait for.\n * @param options - The options.\n * @param options.timeout - The timeout in milliseconds.\n * @param options.message - The error message to throw if the condition is not\n * met.\n * @returns A promise that resolves when the condition is met. The promise\n * resolves to the return value of the condition function.\n */\nexport async function waitFor<Result>(\n fn: () => Promise<Result>,\n { timeout = 3000, message }: WaitForOptions = {},\n) {\n try {\n let result: Result | undefined;\n\n await waitForPuppeteer(\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async () => {\n // Puppeteer's `waitFor` function does not support returning a value\n // from the condition function, so we need to use a variable outside\n // the scope of the function.\n result = await fn();\n },\n {\n timeout,\n },\n );\n\n assert(result !== undefined);\n return result;\n } catch (error) {\n if (message) {\n throw new Error(message);\n }\n\n throw error;\n }\n}\n\n/**\n * Wait for a JSON-RPC response.\n *\n * @param page - The page to wait for the response on.\n * @param type - The type of response to wait for.\n * @returns The JSON-RPC response.\n */\nexport async function waitForResponse(\n page: Page,\n type:\n | HandlerType.OnTransaction\n | HandlerType.OnRpcRequest\n | HandlerType.OnCronjob,\n) {\n log('Waiting for response of type %s.', type);\n\n return await page.evaluate(async (_type) => {\n return new Promise<SnapResponse['response']>((resolve) => {\n window.__SIMULATOR_API__.dispatch({\n type: `${_type}/clearResponse`,\n });\n\n const unsubscribe = window.__SIMULATOR_API__.subscribe(() => {\n const state = window.__SIMULATOR_API__.getState();\n const { pending, response } = state[_type];\n\n if (!pending && response) {\n unsubscribe();\n\n resolve(response);\n }\n });\n });\n }, type);\n}\n"],"names":["waitFor","waitForResponse","log","createModuleLogger","rootLogger","fn","timeout","message","result","waitForPuppeteer","assert","undefined","error","Error","page","type","evaluate","_type","Promise","resolve","window","__SIMULATOR_API__","dispatch","unsubscribe","subscribe","state","getState","pending","response"],"mappings":";;;;;;;;;;;IAmCsBA,OAAO;eAAPA;;IAsCAC,eAAe;eAAfA;;;uBAxEqB;oCACC;wBAIjB;AAc3B,MAAMC,MAAMC,IAAAA,yBAAkB,EAACC,kBAAU,EAAE;AAepC,eAAeJ,QACpBK,EAAyB,EACzB,EAAEC,UAAU,IAAI,EAAEC,OAAO,EAAkB,GAAG,CAAC,CAAC;IAEhD,IAAI;QACF,IAAIC;QAEJ,MAAMC,IAAAA,2BAAgB,EACpB,kEAAkE;QAClE;YACE,oEAAoE;YACpE,oEAAoE;YACpE,6BAA6B;YAC7BD,SAAS,MAAMH;QACjB,GACA;YACEC;QACF;QAGFI,IAAAA,aAAM,EAACF,WAAWG;QAClB,OAAOH;IACT,EAAE,OAAOI,OAAO;QACd,IAAIL,SAAS;YACX,MAAM,IAAIM,MAAMN;QAClB;QAEA,MAAMK;IACR;AACF;AASO,eAAeX,gBACpBa,IAAU,EACVC,IAGyB;IAEzBb,IAAI,oCAAoCa;IAExC,OAAO,MAAMD,KAAKE,QAAQ,CAAC,OAAOC;QAChC,OAAO,IAAIC,QAAkC,CAACC;YAC5CC,OAAOC,iBAAiB,CAACC,QAAQ,CAAC;gBAChCP,MAAM,CAAC,EAAEE,MAAM,cAAc,CAAC;YAChC;YAEA,MAAMM,cAAcH,OAAOC,iBAAiB,CAACG,SAAS,CAAC;gBACrD,MAAMC,QAAQL,OAAOC,iBAAiB,CAACK,QAAQ;gBAC/C,MAAM,EAAEC,OAAO,EAAEC,QAAQ,EAAE,GAAGH,KAAK,CAACR,MAAM;gBAE1C,IAAI,CAACU,WAAWC,UAAU;oBACxBL;oBAEAJ,QAAQS;gBACV;YACF;QACF;IACF,GAAGb;AACL"}
|
package/dist/cjs/matchers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/matchers.ts"],"sourcesContent":["/* eslint-disable no-invalid-this */\n\n// Note: Because this file imports from `@jest/globals`, it can only be used in\n// a Jest environment. This is why it's not exported from the index file.\n\nimport { expect } from '@jest/globals';\nimport { NotificationType } from '@metamask/rpc-methods';\nimport { Component } from '@metamask/snaps-ui';\nimport { EnumToUnion } from '@metamask/snaps-utils';\nimport { hasProperty, Json } from '@metamask/utils';\nimport type { MatcherFunction } from 'expect';\nimport {\n diff,\n matcherErrorMessage,\n matcherHint,\n MatcherHintOptions,\n printReceived,\n printWithType,\n RECEIVED_COLOR,\n} from 'jest-matcher-utils';\nimport { is } from 'superstruct';\n\nimport { InterfaceStruct, SnapResponseStruct } from './internals';\nimport { SnapResponse } from './types';\n\n/**\n * Ensure that the actual value is a response from the `request` function.\n *\n * @param actual - The actual value.\n * @param matcherName - The name of the matcher.\n * @param options - The matcher options.\n */\nfunction assertActualIsSnapResponse(\n actual: unknown,\n matcherName: string,\n options?: MatcherHintOptions,\n): asserts actual is SnapResponse {\n if (!is(actual, SnapResponseStruct)) {\n throw new Error(\n matcherErrorMessage(\n matcherHint(matcherName, undefined, undefined, options),\n `${RECEIVED_COLOR(\n 'received',\n )} value must be a response from the \\`request\\` function`,\n printWithType('Received', actual, printReceived),\n ),\n );\n }\n}\n\n/**\n * Ensure that the actual value is a response from the `request` function, and\n * that it has a `ui` property.\n *\n * @param actual - The actual value.\n * @param matcherName - The name of the matcher.\n * @param options - The matcher options.\n */\nfunction assertHasInterface(\n actual: unknown,\n matcherName: string,\n options?: MatcherHintOptions,\n): asserts actual is { content: Component } {\n if (!is(actual, InterfaceStruct) || !actual.content) {\n throw new Error(\n matcherErrorMessage(\n matcherHint(matcherName, undefined, undefined, options),\n `${RECEIVED_COLOR('received')} value must have a \\`content\\` property`,\n printWithType('Received', actual, printReceived),\n ),\n );\n }\n}\n\n/**\n * Check if a JSON-RPC response matches the expected value. This matcher is\n * intended to be used with the `expect` global.\n *\n * @param actual - The actual response.\n * @param expected - The expected response.\n * @returns The status and message.\n */\nexport const toRespondWith: MatcherFunction<[expected: Json]> = function (\n actual,\n expected,\n) {\n assertActualIsSnapResponse(actual, 'toRespondWith');\n\n const { response } = actual;\n if (hasProperty(response, 'error')) {\n const message = () =>\n `${this.utils.matcherHint('.toRespondWith')}\\n\\n` +\n `Expected response: ${this.utils.printExpected(expected)}\\n` +\n `Received error: ${this.utils.printReceived(response.error)}`;\n\n return { message, pass: false };\n }\n\n const pass = this.equals(response.result, expected);\n const message = pass\n ? () =>\n `${this.utils.matcherHint('.not.toRespondWith')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(response.result)}`\n : () =>\n `${this.utils.matcherHint('.toRespondWith')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(response.result)}`;\n\n return { message, pass };\n};\n\nexport const toRespondWithError: MatcherFunction<[expected: Json]> = function (\n actual,\n expected,\n) {\n assertActualIsSnapResponse(actual, 'toRespondWithError');\n\n const { response } = actual;\n if (hasProperty(response, 'result')) {\n const message = () =>\n `${this.utils.matcherHint('.toRespondWithError')}\\n\\n` +\n `Expected error: ${this.utils.printExpected(expected)}\\n` +\n `Received result: ${this.utils.printReceived(response.result)}`;\n\n return { message, pass: false };\n }\n\n const pass = this.equals(response.error, expected);\n const message = pass\n ? () =>\n `${this.utils.matcherHint('.not.toRespondWithError')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(response.error)}`\n : () =>\n `${this.utils.matcherHint('.toRespondWithError')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(response.error)}`;\n\n return { message, pass };\n};\n\n/**\n * Check if the snap sent a notification with the expected message. This matcher\n * is intended to be used with the `expect` global.\n *\n * @param actual - The actual response.\n * @param expected - The expected notification message.\n * @param type - The expected notification type.\n * @returns The status and message.\n */\nexport const toSendNotification: MatcherFunction<\n [expected: string, type?: EnumToUnion<NotificationType> | undefined]\n> = async function (actual, expected, type) {\n assertActualIsSnapResponse(actual, 'toSendNotification');\n\n const { notifications } = actual;\n const pass = notifications.some(\n (notification) =>\n this.equals(notification.message, expected) &&\n (type === undefined || notification.type === type),\n );\n\n const message = pass\n ? () =>\n `${this.utils.matcherHint('.not.toSendNotification')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Expected type: ${this.utils.printExpected(type)}\\n` +\n `Received: ${this.utils.printReceived(notifications)}`\n : () =>\n `${this.utils.matcherHint('.toSendNotification')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Expected type: ${this.utils.printExpected(type)}\\n` +\n `Received: ${this.utils.printReceived(notifications)}`;\n\n return { message, pass };\n};\n\nexport const toRender: MatcherFunction<[expected: Component]> = function (\n actual,\n expected,\n) {\n assertHasInterface(actual, 'toRender');\n\n const { content } = actual;\n const pass = this.equals(content, expected);\n\n const difference = diff(expected, content);\n\n const message = pass\n ? () =>\n `${this.utils.matcherHint('.not.toShowInterface')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(content)}` +\n `${difference ? `\\n\\nDifference:\\n\\n${difference}` : ''}`\n : () =>\n `${this.utils.matcherHint('.toShowInterface')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(content)}` +\n `${difference ? `\\n\\nDifference:\\n\\n${difference}` : ''}`;\n\n return { message, pass };\n};\n\nexpect.extend({\n toRespondWith,\n toRespondWithError,\n toSendNotification,\n toRender,\n});\n"],"names":["toRespondWith","toRespondWithError","toSendNotification","toRender","assertActualIsSnapResponse","actual","matcherName","options","is","SnapResponseStruct","Error","matcherErrorMessage","matcherHint","undefined","RECEIVED_COLOR","printWithType","printReceived","assertHasInterface","InterfaceStruct","content","expected","response","hasProperty","message","utils","printExpected","error","pass","equals","result","type","notifications","some","notification","difference","diff","expect","extend"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/matchers.ts"],"sourcesContent":["/* eslint-disable no-invalid-this */\n\n// Note: Because this file imports from `@jest/globals`, it can only be used in\n// a Jest environment. This is why it's not exported from the index file.\n\nimport { expect } from '@jest/globals';\nimport type { NotificationType } from '@metamask/rpc-methods';\nimport type { Component } from '@metamask/snaps-ui';\nimport type { EnumToUnion } from '@metamask/snaps-utils';\nimport type { Json } from '@metamask/utils';\nimport { hasProperty } from '@metamask/utils';\nimport type { MatcherFunction } from 'expect';\nimport type { MatcherHintOptions } from 'jest-matcher-utils';\nimport {\n diff,\n matcherErrorMessage,\n matcherHint,\n printReceived,\n printWithType,\n RECEIVED_COLOR,\n} from 'jest-matcher-utils';\nimport { is } from 'superstruct';\n\nimport { InterfaceStruct, SnapResponseStruct } from './internals';\nimport type { SnapResponse } from './types';\n\n/**\n * Ensure that the actual value is a response from the `request` function.\n *\n * @param actual - The actual value.\n * @param matcherName - The name of the matcher.\n * @param options - The matcher options.\n */\nfunction assertActualIsSnapResponse(\n actual: unknown,\n matcherName: string,\n options?: MatcherHintOptions,\n): asserts actual is SnapResponse {\n if (!is(actual, SnapResponseStruct)) {\n throw new Error(\n matcherErrorMessage(\n matcherHint(matcherName, undefined, undefined, options),\n `${RECEIVED_COLOR(\n 'received',\n )} value must be a response from the \\`request\\` function`,\n printWithType('Received', actual, printReceived),\n ),\n );\n }\n}\n\n/**\n * Ensure that the actual value is a response from the `request` function, and\n * that it has a `ui` property.\n *\n * @param actual - The actual value.\n * @param matcherName - The name of the matcher.\n * @param options - The matcher options.\n */\nfunction assertHasInterface(\n actual: unknown,\n matcherName: string,\n options?: MatcherHintOptions,\n): asserts actual is { content: Component } {\n if (!is(actual, InterfaceStruct) || !actual.content) {\n throw new Error(\n matcherErrorMessage(\n matcherHint(matcherName, undefined, undefined, options),\n `${RECEIVED_COLOR('received')} value must have a \\`content\\` property`,\n printWithType('Received', actual, printReceived),\n ),\n );\n }\n}\n\n/**\n * Check if a JSON-RPC response matches the expected value. This matcher is\n * intended to be used with the `expect` global.\n *\n * @param actual - The actual response.\n * @param expected - The expected response.\n * @returns The status and message.\n */\nexport const toRespondWith: MatcherFunction<[expected: Json]> = function (\n actual,\n expected,\n) {\n assertActualIsSnapResponse(actual, 'toRespondWith');\n\n const { response } = actual;\n if (hasProperty(response, 'error')) {\n const message = () =>\n `${this.utils.matcherHint('.toRespondWith')}\\n\\n` +\n `Expected response: ${this.utils.printExpected(expected)}\\n` +\n `Received error: ${this.utils.printReceived(response.error)}`;\n\n return { message, pass: false };\n }\n\n const pass = this.equals(response.result, expected);\n const message = pass\n ? () =>\n `${this.utils.matcherHint('.not.toRespondWith')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(response.result)}`\n : () =>\n `${this.utils.matcherHint('.toRespondWith')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(response.result)}`;\n\n return { message, pass };\n};\n\nexport const toRespondWithError: MatcherFunction<[expected: Json]> = function (\n actual,\n expected,\n) {\n assertActualIsSnapResponse(actual, 'toRespondWithError');\n\n const { response } = actual;\n if (hasProperty(response, 'result')) {\n const message = () =>\n `${this.utils.matcherHint('.toRespondWithError')}\\n\\n` +\n `Expected error: ${this.utils.printExpected(expected)}\\n` +\n `Received result: ${this.utils.printReceived(response.result)}`;\n\n return { message, pass: false };\n }\n\n const pass = this.equals(response.error, expected);\n const message = pass\n ? () =>\n `${this.utils.matcherHint('.not.toRespondWithError')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(response.error)}`\n : () =>\n `${this.utils.matcherHint('.toRespondWithError')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(response.error)}`;\n\n return { message, pass };\n};\n\n/**\n * Check if the snap sent a notification with the expected message. This matcher\n * is intended to be used with the `expect` global.\n *\n * @param actual - The actual response.\n * @param expected - The expected notification message.\n * @param type - The expected notification type.\n * @returns The status and message.\n */\nexport const toSendNotification: MatcherFunction<\n [expected: string, type?: EnumToUnion<NotificationType> | undefined]\n> = async function (actual, expected, type) {\n assertActualIsSnapResponse(actual, 'toSendNotification');\n\n const { notifications } = actual;\n const pass = notifications.some(\n (notification) =>\n this.equals(notification.message, expected) &&\n (type === undefined || notification.type === type),\n );\n\n const message = pass\n ? () =>\n `${this.utils.matcherHint('.not.toSendNotification')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Expected type: ${this.utils.printExpected(type)}\\n` +\n `Received: ${this.utils.printReceived(notifications)}`\n : () =>\n `${this.utils.matcherHint('.toSendNotification')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Expected type: ${this.utils.printExpected(type)}\\n` +\n `Received: ${this.utils.printReceived(notifications)}`;\n\n return { message, pass };\n};\n\nexport const toRender: MatcherFunction<[expected: Component]> = function (\n actual,\n expected,\n) {\n assertHasInterface(actual, 'toRender');\n\n const { content } = actual;\n const pass = this.equals(content, expected);\n\n const difference = diff(expected, content);\n\n const message = pass\n ? () =>\n `${this.utils.matcherHint('.not.toShowInterface')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(content)}` +\n `${difference ? `\\n\\nDifference:\\n\\n${difference}` : ''}`\n : () =>\n `${this.utils.matcherHint('.toShowInterface')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(content)}` +\n `${difference ? `\\n\\nDifference:\\n\\n${difference}` : ''}`;\n\n return { message, pass };\n};\n\nexpect.extend({\n toRespondWith,\n toRespondWithError,\n toSendNotification,\n toRender,\n});\n"],"names":["toRespondWith","toRespondWithError","toSendNotification","toRender","assertActualIsSnapResponse","actual","matcherName","options","is","SnapResponseStruct","Error","matcherErrorMessage","matcherHint","undefined","RECEIVED_COLOR","printWithType","printReceived","assertHasInterface","InterfaceStruct","content","expected","response","hasProperty","message","utils","printExpected","error","pass","equals","result","type","notifications","some","notification","difference","diff","expect","extend"],"mappings":"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"}
|
package/dist/cjs/options.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/options.ts"],"sourcesContent":["import {\n boolean,\n create,\n defaulted,\n
|
|
1
|
+
{"version":3,"sources":["../../src/options.ts"],"sourcesContent":["import type { Infer } from 'superstruct';\nimport {\n boolean,\n create,\n defaulted,\n number,\n object,\n optional,\n string,\n type,\n} from 'superstruct';\n\nconst SnapsEnvironmentOptionsStruct = type({\n executionEnvironmentUrl: optional(string()),\n simulatorUrl: optional(string()),\n keepAlive: defaulted(boolean(), false),\n\n server: defaulted(\n object({\n enabled: defaulted(boolean(), true),\n port: defaulted(number(), 0),\n root: defaulted(string(), process.cwd()),\n }),\n {},\n ),\n\n browser: defaulted(\n object({\n headless: defaulted(boolean(), true),\n }),\n {},\n ),\n});\n\n/**\n * The options for the environment. These can be specified in the Jest\n * configuration under `testEnvironmentOptions`.\n *\n * @example\n * ```json\n * {\n * \"testEnvironment\": \"@metamask/snaps-jest\",\n * \"testEnvironmentOptions\": {\n * \"executionEnvironmentUrl\": \"http://localhost:8080\",\n * \"server\": {\n * \"port\": 8080,\n * /* ... *\\/\n * }\n * }\n * }\n * ```\n * @property executionEnvironmentUrl - The URL of the execution environment. If\n * this is not provided, the execution environment will be served from the\n * built-in HTTP server.\n * @property simulatorUrl - The URL of the simulator. If this is not provided,\n * the simulator will be served from the built-in HTTP server.\n * @property keepAlive - Whether to keep the browser open after the tests have\n * finished. This is useful for debugging. Defaults to `false`.\n * @property server - The options for the built-in HTTP server.\n * @property server.enabled - Whether to run the built-in HTTP server. Defaults\n * to `true`.\n * @property server.port - The port to use for the built-in HTTP server. If this\n * is not provided, a random available port will be used.\n * @property server.root - The root directory to serve from the built-in HTTP\n * server. Defaults to the current working directory. This is assumed to be the\n * directory containing the snap manifest and `dist` files. If this is a\n * relative path, it will be resolved relative to the current working directory.\n * @property browser - The options for the browser.\n * @property browser.headless - Whether to run the browser in headless mode.\n * Defaults to `true`.\n */\nexport type SnapsEnvironmentOptions = Infer<\n typeof SnapsEnvironmentOptionsStruct\n>;\n\n/**\n * Get the environment options. This validates the options, and returns the\n * default options if none are provided.\n *\n * @param testEnvironmentOptions - The test environment options as defined in\n * the Jest configuration.\n * @returns The environment options.\n */\nexport function getOptions(testEnvironmentOptions: Record<string, unknown>) {\n return create(testEnvironmentOptions, SnapsEnvironmentOptionsStruct);\n}\n"],"names":["getOptions","SnapsEnvironmentOptionsStruct","type","executionEnvironmentUrl","optional","string","simulatorUrl","keepAlive","defaulted","boolean","server","object","enabled","port","number","root","process","cwd","browser","headless","testEnvironmentOptions","create"],"mappings":";;;;+BAmFgBA;;;eAAAA;;;6BAzET;AAEP,MAAMC,gCAAgCC,IAAAA,iBAAI,EAAC;IACzCC,yBAAyBC,IAAAA,qBAAQ,EAACC,IAAAA,mBAAM;IACxCC,cAAcF,IAAAA,qBAAQ,EAACC,IAAAA,mBAAM;IAC7BE,WAAWC,IAAAA,sBAAS,EAACC,IAAAA,oBAAO,KAAI;IAEhCC,QAAQF,IAAAA,sBAAS,EACfG,IAAAA,mBAAM,EAAC;QACLC,SAASJ,IAAAA,sBAAS,EAACC,IAAAA,oBAAO,KAAI;QAC9BI,MAAML,IAAAA,sBAAS,EAACM,IAAAA,mBAAM,KAAI;QAC1BC,MAAMP,IAAAA,sBAAS,EAACH,IAAAA,mBAAM,KAAIW,QAAQC,GAAG;IACvC,IACA,CAAC;IAGHC,SAASV,IAAAA,sBAAS,EAChBG,IAAAA,mBAAM,EAAC;QACLQ,UAAUX,IAAAA,sBAAS,EAACC,IAAAA,oBAAO,KAAI;IACjC,IACA,CAAC;AAEL;AAmDO,SAAST,WAAWoB,sBAA+C;IACxE,OAAOC,IAAAA,mBAAM,EAACD,wBAAwBnB;AACxC"}
|
package/dist/cjs/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/types.ts"],"sourcesContent":["import { NotificationType } from '@metamask/rpc-methods';\nimport { Component } from '@metamask/snaps-ui';\nimport { EnumToUnion } from '@metamask/snaps-utils';\nimport { JsonRpcId, JsonRpcParams } from '@metamask/utils';\nimport { Infer } from 'superstruct';\n\nimport {\n Mock,\n MockJsonRpcOptions,\n MockOptions,\n SnapOptionsStruct,\n SnapResponseStruct,\n TransactionOptionsStruct,\n} from './internals';\n\n/* eslint-disable @typescript-eslint/consistent-type-definitions */\ndeclare module 'expect' {\n interface AsymmetricMatchers {\n toRespondWith(response: unknown): void;\n toRespondWithError(error: unknown): void;\n toSendNotification(\n message: string,\n type?: EnumToUnion<NotificationType>,\n ): void;\n toRender(component: Component): void;\n }\n\n // Ideally we would use `Matchers<Result>` instead of `Matchers<R>`, but\n // TypeScript doesn't allow this:\n // TS2428: All declarations of 'Matchers' must have identical type parameters.\n interface Matchers<R> {\n toRespondWith(response: unknown): R;\n toRespondWithError(error: unknown): R;\n toSendNotification(\n message: string,\n type?: EnumToUnion<NotificationType>,\n ): R;\n toRender(component: Component): R;\n }\n}\n/* eslint-enable @typescript-eslint/consistent-type-definitions */\n\n/**\n * Deeply partialize a type.\n *\n * @template Type - The type to partialize.\n * @returns The deeply partialized type.\n * @example\n * ```ts\n * type Foo = {\n * bar: {\n * baz: string;\n * };\n * qux: number;\n * };\n *\n * type PartialFoo = DeepPartial<Foo>;\n * // { bar?: { baz?: string; }; qux?: number; }\n * ```\n */\nexport type DeepPartial<Type> = {\n [Key in keyof Type]?: Type[Key] extends Record<string, unknown>\n ? DeepPartial<Type[Key]>\n : Type[Key];\n};\n\nexport type RequestOptions = {\n /**\n * The JSON-RPC request ID.\n */\n id?: JsonRpcId;\n\n /**\n * The JSON-RPC method.\n */\n method: string;\n\n /**\n * The JSON-RPC params.\n */\n params?: JsonRpcParams;\n\n /**\n * The origin to send the request from.\n */\n origin?: string;\n};\n\n/**\n * The `runCronjob` options. This is the same as {@link RequestOptions}, except\n * that it does not have an `origin` property.\n */\nexport type CronjobOptions = Omit<RequestOptions, 'origin'>;\n\n/**\n * The options to use for transaction requests.\n *\n * @property chainId - The CAIP-2 chain ID to send the transaction on. Defaults\n * to `eip155:1`.\n * @property origin - The origin to send the transaction from. Defaults to\n * `metamask.io`.\n * @property from - The address to send the transaction from. Defaults to a\n * randomly generated address.\n * @property to - The address to send the transaction to. Defaults to a randomly\n * generated address.\n * @property value - The value to send with the transaction. Defaults to `0`.\n * @property data - The data to send with the transaction. Defaults to `0x`.\n * @property gasLimit - The gas limit to use for the transaction. Defaults to\n * `21_000`.\n * @property maxFeePerGas - The maximum fee per gas to use for the transaction.\n * Defaults to `1`.\n * @property maxPriorityFeePerGas - The maximum priority fee per gas to use for\n * the transaction. Defaults to `1`.\n * @property nonce - The nonce to use for the transaction. Defaults to `0`.\n */\nexport type TransactionOptions = Infer<typeof TransactionOptionsStruct>;\n\n/**\n * The options to use for requests to the snap.\n *\n * @property timeout - The timeout in milliseconds to use. Defaults to `1000`.\n */\nexport type SnapOptions = Infer<typeof SnapOptionsStruct>;\n\n/**\n * A `snap_dialog` alert interface.\n */\nexport type SnapAlertInterface = {\n /**\n * The type of the interface. This is always `alert`.\n */\n type: 'alert';\n\n /**\n * The content to show in the alert.\n */\n content: Component;\n\n /**\n * Close the alert.\n */\n ok(): Promise<void>;\n};\n\n/**\n * A `snap_dialog` confirmation interface.\n */\nexport type SnapConfirmationInterface = {\n /**\n * The type of the interface. This is always `confirmation`.\n */\n type: 'confirmation';\n\n /**\n * The content to show in the confirmation.\n */\n content: Component;\n\n /**\n * Close the confirmation.\n */\n ok(): Promise<void>;\n\n /**\n * Cancel the confirmation.\n */\n cancel(): Promise<void>;\n};\n\n/**\n * A `snap_dialog` prompt interface.\n */\nexport type SnapPromptInterface = {\n /**\n * The type of the interface. This is always `prompt`.\n */\n type: 'prompt';\n\n /**\n * The content to show in the prompt.\n */\n content: Component;\n\n /**\n * Close the prompt.\n *\n * @param value - The value to close the prompt with.\n */\n ok(value?: string): Promise<void>;\n\n /**\n * Cancel the prompt.\n */\n cancel(): Promise<void>;\n};\n\nexport type SnapInterface =\n | SnapAlertInterface\n | SnapConfirmationInterface\n | SnapPromptInterface;\n\nexport type SnapRequestObject = {\n /**\n * Get a user interface object from a snap. This will throw an error if the\n * snap does not show a user interface within the timeout.\n *\n * @param options - The options to use.\n * @param options.timeout - The timeout in milliseconds to use. Defaults to\n * `1000`.\n * @returns The user interface object.\n */\n getInterface(options?: SnapOptions): Promise<SnapInterface>;\n};\n\n/**\n * A pending request object. This is a promise with extra\n * {@link SnapRequestObject} fields.\n */\nexport type SnapRequest = Promise<SnapResponse> & SnapRequestObject;\n\n/**\n * This is the main entry point to interact with the snap. It is returned by\n * {@link installSnap}, and has methods to send requests to the snap.\n *\n * @example\n * ```ts\n * import { installSnap } from '@metamask/snaps-jest';\n *\n * const snap = await installSnap();\n * const response = await snap.request({ method: 'hello' });\n *\n * expect(response).toRespondWith('Hello, world!');\n * ```\n */\nexport type Snap = {\n /**\n * Send a JSON-RPC request to the snap.\n *\n * @param request - The request. This is similar to a JSON-RPC request, but\n * has an extra `origin` field.\n * @returns The response promise, with extra {@link SnapRequestObject} fields.\n */\n request(request: RequestOptions): SnapRequest;\n\n /**\n * Send a transaction to the snap.\n *\n * @param transaction - The transaction. This is similar to an Ethereum\n * transaction object, but has an extra `origin` field. Any missing fields\n * will be filled in with default values.\n * @returns The response.\n */\n sendTransaction(\n transaction?: Partial<TransactionOptions>,\n ): Promise<SnapResponse>;\n\n /**\n * Run a cronjob in the snap. This is similar to {@link request}, but the\n * request will be sent to the `onCronjob` method of the snap.\n *\n * @param cronjob - The cronjob request. This is similar to a JSON-RPC\n * request, and is normally specified in the snap manifest, under the\n * `endowment:cronjob` permission.\n * @returns The response promise, with extra {@link SnapRequestObject} fields.\n */\n runCronjob(cronjob: CronjobOptions): SnapRequest;\n\n /**\n * Close the page running the snap. This is mainly useful for cleaning up\n * the test environment, and calling it is not strictly necessary.\n *\n * @returns A promise that resolves when the page is closed.\n */\n // TODO: Find a way to do this automatically.\n close(): Promise<void>;\n\n /**\n * Enable network mocking for the snap.\n *\n * @param options - The options for the network mocking.\n * @returns A {@link Mock} object, with an `unmock` function.\n */\n mock(options: DeepPartial<MockOptions>): Promise<Mock>;\n\n /**\n * Enable JSON-RPC provider mocking for the snap. This will mock any requests\n * sent through the `ethereum` global, with the specified `method`.\n *\n * @param options - The options for the JSON-RPC mocking.\n * @param options.method - The JSON-RPC method to mock, e.g.,\n * `eth_blockNumber`.\n * @param options.result - The JSON value to return.\n * @returns A {@link Mock} object, with an `unmock` function.\n */\n mockJsonRpc(options: MockJsonRpcOptions): Promise<Mock>;\n};\n\nexport type SnapResponse = Infer<typeof SnapResponseStruct>;\n\nexport { NotificationType } from '@metamask/rpc-methods';\n"],"names":["NotificationType"],"mappings":";;;;+
|
|
1
|
+
{"version":3,"sources":["../../src/types.ts"],"sourcesContent":["import type { NotificationType } from '@metamask/rpc-methods';\nimport type { Component } from '@metamask/snaps-ui';\nimport type { EnumToUnion } from '@metamask/snaps-utils';\nimport type { JsonRpcId, JsonRpcParams } from '@metamask/utils';\nimport type { Infer } from 'superstruct';\n\nimport type {\n Mock,\n MockJsonRpcOptions,\n MockOptions,\n SnapOptionsStruct,\n SnapResponseStruct,\n TransactionOptionsStruct,\n} from './internals';\n\n/* eslint-disable @typescript-eslint/consistent-type-definitions */\ndeclare module 'expect' {\n interface AsymmetricMatchers {\n toRespondWith(response: unknown): void;\n toRespondWithError(error: unknown): void;\n toSendNotification(\n message: string,\n type?: EnumToUnion<NotificationType>,\n ): void;\n toRender(component: Component): void;\n }\n\n // Ideally we would use `Matchers<Result>` instead of `Matchers<R>`, but\n // TypeScript doesn't allow this:\n // TS2428: All declarations of 'Matchers' must have identical type parameters.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n interface Matchers<R> {\n toRespondWith(response: unknown): R;\n toRespondWithError(error: unknown): R;\n toSendNotification(\n message: string,\n type?: EnumToUnion<NotificationType>,\n ): R;\n toRender(component: Component): R;\n }\n}\n/* eslint-enable @typescript-eslint/consistent-type-definitions */\n\n/**\n * Deeply partialize a type.\n *\n * @template Type - The type to partialize.\n * @returns The deeply partialized type.\n * @example\n * ```ts\n * type Foo = {\n * bar: {\n * baz: string;\n * };\n * qux: number;\n * };\n *\n * type PartialFoo = DeepPartial<Foo>;\n * // { bar?: { baz?: string; }; qux?: number; }\n * ```\n */\nexport type DeepPartial<Type> = {\n [Key in keyof Type]?: Type[Key] extends Record<string, unknown>\n ? DeepPartial<Type[Key]>\n : Type[Key];\n};\n\nexport type RequestOptions = {\n /**\n * The JSON-RPC request ID.\n */\n id?: JsonRpcId;\n\n /**\n * The JSON-RPC method.\n */\n method: string;\n\n /**\n * The JSON-RPC params.\n */\n params?: JsonRpcParams;\n\n /**\n * The origin to send the request from.\n */\n origin?: string;\n};\n\n/**\n * The `runCronjob` options. This is the same as {@link RequestOptions}, except\n * that it does not have an `origin` property.\n */\nexport type CronjobOptions = Omit<RequestOptions, 'origin'>;\n\n/**\n * The options to use for transaction requests.\n *\n * @property chainId - The CAIP-2 chain ID to send the transaction on. Defaults\n * to `eip155:1`.\n * @property origin - The origin to send the transaction from. Defaults to\n * `metamask.io`.\n * @property from - The address to send the transaction from. Defaults to a\n * randomly generated address.\n * @property to - The address to send the transaction to. Defaults to a randomly\n * generated address.\n * @property value - The value to send with the transaction. Defaults to `0`.\n * @property data - The data to send with the transaction. Defaults to `0x`.\n * @property gasLimit - The gas limit to use for the transaction. Defaults to\n * `21_000`.\n * @property maxFeePerGas - The maximum fee per gas to use for the transaction.\n * Defaults to `1`.\n * @property maxPriorityFeePerGas - The maximum priority fee per gas to use for\n * the transaction. Defaults to `1`.\n * @property nonce - The nonce to use for the transaction. Defaults to `0`.\n */\nexport type TransactionOptions = Infer<typeof TransactionOptionsStruct>;\n\n/**\n * The options to use for requests to the snap.\n *\n * @property timeout - The timeout in milliseconds to use. Defaults to `1000`.\n */\nexport type SnapOptions = Infer<typeof SnapOptionsStruct>;\n\n/**\n * A `snap_dialog` alert interface.\n */\nexport type SnapAlertInterface = {\n /**\n * The type of the interface. This is always `alert`.\n */\n type: 'alert';\n\n /**\n * The content to show in the alert.\n */\n content: Component;\n\n /**\n * Close the alert.\n */\n ok(): Promise<void>;\n};\n\n/**\n * A `snap_dialog` confirmation interface.\n */\nexport type SnapConfirmationInterface = {\n /**\n * The type of the interface. This is always `confirmation`.\n */\n type: 'confirmation';\n\n /**\n * The content to show in the confirmation.\n */\n content: Component;\n\n /**\n * Close the confirmation.\n */\n ok(): Promise<void>;\n\n /**\n * Cancel the confirmation.\n */\n cancel(): Promise<void>;\n};\n\n/**\n * A `snap_dialog` prompt interface.\n */\nexport type SnapPromptInterface = {\n /**\n * The type of the interface. This is always `prompt`.\n */\n type: 'prompt';\n\n /**\n * The content to show in the prompt.\n */\n content: Component;\n\n /**\n * Close the prompt.\n *\n * @param value - The value to close the prompt with.\n */\n ok(value?: string): Promise<void>;\n\n /**\n * Cancel the prompt.\n */\n cancel(): Promise<void>;\n};\n\nexport type SnapInterface =\n | SnapAlertInterface\n | SnapConfirmationInterface\n | SnapPromptInterface;\n\nexport type SnapRequestObject = {\n /**\n * Get a user interface object from a snap. This will throw an error if the\n * snap does not show a user interface within the timeout.\n *\n * @param options - The options to use.\n * @param options.timeout - The timeout in milliseconds to use. Defaults to\n * `1000`.\n * @returns The user interface object.\n */\n getInterface(options?: SnapOptions): Promise<SnapInterface>;\n};\n\n/**\n * A pending request object. This is a promise with extra\n * {@link SnapRequestObject} fields.\n */\nexport type SnapRequest = Promise<SnapResponse> & SnapRequestObject;\n\n/**\n * This is the main entry point to interact with the snap. It is returned by\n * {@link installSnap}, and has methods to send requests to the snap.\n *\n * @example\n * ```ts\n * import { installSnap } from '@metamask/snaps-jest';\n *\n * const snap = await installSnap();\n * const response = await snap.request({ method: 'hello' });\n *\n * expect(response).toRespondWith('Hello, world!');\n * ```\n */\nexport type Snap = {\n /**\n * Send a JSON-RPC request to the snap.\n *\n * @param request - The request. This is similar to a JSON-RPC request, but\n * has an extra `origin` field.\n * @returns The response promise, with extra {@link SnapRequestObject} fields.\n */\n request(request: RequestOptions): SnapRequest;\n\n /**\n * Send a transaction to the snap.\n *\n * @param transaction - The transaction. This is similar to an Ethereum\n * transaction object, but has an extra `origin` field. Any missing fields\n * will be filled in with default values.\n * @returns The response.\n */\n sendTransaction(\n transaction?: Partial<TransactionOptions>,\n ): Promise<SnapResponse>;\n\n /**\n * Run a cronjob in the snap. This is similar to {@link request}, but the\n * request will be sent to the `onCronjob` method of the snap.\n *\n * @param cronjob - The cronjob request. This is similar to a JSON-RPC\n * request, and is normally specified in the snap manifest, under the\n * `endowment:cronjob` permission.\n * @returns The response promise, with extra {@link SnapRequestObject} fields.\n */\n runCronjob(cronjob: CronjobOptions): SnapRequest;\n\n /**\n * Close the page running the snap. This is mainly useful for cleaning up\n * the test environment, and calling it is not strictly necessary.\n *\n * @returns A promise that resolves when the page is closed.\n */\n // TODO: Find a way to do this automatically.\n close(): Promise<void>;\n\n /**\n * Enable network mocking for the snap.\n *\n * @param options - The options for the network mocking.\n * @returns A {@link Mock} object, with an `unmock` function.\n */\n mock(options: DeepPartial<MockOptions>): Promise<Mock>;\n\n /**\n * Enable JSON-RPC provider mocking for the snap. This will mock any requests\n * sent through the `ethereum` global, with the specified `method`.\n *\n * @param options - The options for the JSON-RPC mocking.\n * @param options.method - The JSON-RPC method to mock, e.g.,\n * `eth_blockNumber`.\n * @param options.result - The JSON value to return.\n * @returns A {@link Mock} object, with an `unmock` function.\n */\n mockJsonRpc(options: MockJsonRpcOptions): Promise<Mock>;\n};\n\nexport type SnapResponse = Infer<typeof SnapResponseStruct>;\n\nexport { NotificationType } from '@metamask/rpc-methods';\n"],"names":["NotificationType"],"mappings":";;;;+BA4SSA;;;eAAAA,4BAAgB;;;4BAAQ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/environment.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"sources":["../../src/environment.ts"],"sourcesContent":["import type {\n EnvironmentContext,\n JestEnvironmentConfig,\n} from '@jest/environment';\nimport { assert, createModuleLogger } from '@metamask/utils';\nimport type { Server } from 'http';\nimport NodeEnvironment from 'jest-environment-node';\nimport type { AddressInfo } from 'net';\nimport type { Browser } from 'puppeteer';\nimport { remote } from 'webdriverio';\n\nimport { rootLogger, startServer } from './internals';\nimport type { SnapsEnvironmentOptions } from './options';\nimport { getOptions } from './options';\n\n/* eslint-disable */\ndeclare global {\n const browser: WebdriverIO.Browser;\n const snapsEnvironment: SnapsEnvironment;\n}\n/* eslint-enable */\n\nconst log = createModuleLogger(rootLogger, 'environment');\n\nexport class SnapsEnvironment extends NodeEnvironment {\n // `browser` is always set in the environment setup function. To avoid needing\n // to check for `undefined` everywhere, we use a type assertion here.\n browser!: WebdriverIO.Browser;\n\n #options: SnapsEnvironmentOptions;\n\n #server: Server | undefined;\n\n /**\n * Constructor.\n *\n * @param options - The environment options.\n * @param context - The environment context.\n */\n constructor(options: JestEnvironmentConfig, context: EnvironmentContext) {\n super(options, context);\n this.#options = getOptions(options.projectConfig.testEnvironmentOptions);\n }\n\n /**\n * Set up the environment. This starts the built-in HTTP server, and creates a\n * new browser instance.\n */\n async setup() {\n await super.setup();\n\n if (this.#options.server.enabled) {\n log('Starting server.');\n this.#server = await startServer(this.#options.server);\n }\n\n const args = [];\n if (this.#options.browser.headless) {\n args.push('--headless', '--disable-gpu');\n }\n\n log('Starting browser.');\n this.browser = await remote({\n logLevel: 'error',\n capabilities: {\n browserName: 'chrome',\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'goog:chromeOptions': {\n args,\n },\n },\n });\n\n this.global.browser = this.browser;\n this.global.snapsEnvironment = this;\n }\n\n /**\n * Tear down the environment. This closes the browser, and stops the built-in\n * HTTP server.\n */\n async teardown() {\n if (this.#options.keepAlive) {\n log('Not tearing down environment because keepAlive is enabled.');\n return;\n }\n\n log('Closing browser, and stopping server.');\n await this.browser?.deleteSession();\n this.#server?.close();\n\n await super.teardown();\n }\n\n /**\n * Get the URL to the simulator, including the environment URL.\n *\n * @returns The simulator URL.\n * @throws If the server is not running.\n */\n get url() {\n assert(this.#server, 'Server is not running.');\n\n const { port } = this.#server.address() as AddressInfo;\n const simulatorUrl =\n this.#options.simulatorUrl ?? `http://localhost:${port}/simulator/`;\n\n const executionEnvironmentUrl =\n this.#options.executionEnvironmentUrl ??\n `http://localhost:${port}/environment/`;\n\n return `${simulatorUrl}?environment=${encodeURIComponent(\n executionEnvironmentUrl,\n )}`;\n }\n\n /**\n * Get the snap ID for the current environment, which is used if no snap ID is\n * passed to {@link installSnap}. This assumes that the built-in server is\n * running.\n *\n * @returns The snap ID.\n * @throws If the server is not running.\n */\n get snapId() {\n assert(\n this.#server,\n 'You must specify a snap ID, because the built-in server is not running.',\n );\n\n const { port } = this.#server.address() as AddressInfo;\n return `local:http://localhost:${port}`;\n }\n\n /**\n * Create a new page, and attach logging handlers.\n *\n * @param url - The page URL. Defaults to the specified Snaps Simulator URL,\n * or the default simulator URL if none is specified.\n * @param timeout - The page timeout, in milliseconds.\n * @returns The new page.\n */\n async createPage(url: string = this.url, timeout = 10000) {\n const puppeteer = (await this.browser.getPuppeteer()) as unknown as Browser;\n const page = await puppeteer.newPage();\n\n page.setDefaultTimeout(timeout);\n page.setDefaultNavigationTimeout(timeout);\n\n // Give the page permission to show notifications. This is required for\n // testing `snap_notify`.\n await page.browserContext().overridePermissions(url, ['notifications']);\n\n // `networkidle0` is used to ensure that the page is fully loaded. This\n // makes it wait for no requests to be made, which guarantees that the page\n // is ready.\n await page.goto(url, { waitUntil: 'networkidle0' });\n\n const browserLog = createModuleLogger(rootLogger, 'browser');\n\n page\n // This is fired when the page calls `console.log` or similar.\n .on('console', (message) => {\n browserLog(`[${message.type()}] ${message.text()}`);\n })\n\n // This is fired when the page throws an error.\n .on('pageerror', ({ message }) => {\n browserLog(`[page error] ${message}`);\n });\n\n return page;\n }\n}\n\nexport default SnapsEnvironment;\n"],"names":["assert","createModuleLogger","NodeEnvironment","remote","rootLogger","startServer","getOptions","log","SnapsEnvironment","setup","options","server","enabled","args","browser","headless","push","logLevel","capabilities","browserName","global","snapsEnvironment","teardown","keepAlive","deleteSession","close","url","port","address","simulatorUrl","executionEnvironmentUrl","encodeURIComponent","snapId","createPage","timeout","puppeteer","getPuppeteer","page","newPage","setDefaultTimeout","setDefaultNavigationTimeout","browserContext","overridePermissions","goto","waitUntil","browserLog","on","message","type","text","constructor","context","projectConfig","testEnvironmentOptions"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/internals/interface.ts"],"sourcesContent":["import { DialogType } from '@metamask/rpc-methods';\nimport { assert } from '@metamask/utils';\nimport { Page } from 'puppeteer';\nimport { create } from 'superstruct';\n\nimport { SnapInterface, SnapOptions } from '../types';\nimport { SnapOptionsStruct } from './structs';\nimport { waitFor } from './wait-for';\n\n/**\n * Get the current snap user interface (i.e., dialog). This will throw an error\n * if the snap does not show a user interface within the timeout.\n *\n * @param page - The page to get the interface from.\n * @param options - The options to use.\n * @param options.timeout - The timeout in milliseconds to use. Defaults to\n * `1000`.\n * @returns The user interface object.\n */\nexport async function getInterface(\n page: Page,\n options: SnapOptions = {},\n): Promise<SnapInterface> {\n const { timeout } = create(options, SnapOptionsStruct);\n\n const { type, node: content } = await waitFor(\n async () => {\n const ui = await page.evaluate(() => {\n const state = window.__SIMULATOR_API__.getState();\n return state.simulation.ui;\n });\n\n assert(ui);\n return ui;\n },\n {\n timeout,\n message: 'Timed out waiting for snap interface to be shown.',\n },\n );\n\n switch (type) {\n case DialogType.Alert:\n return {\n type: 'alert',\n content,\n\n ok: async () => {\n await page.evaluate(() => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload: null,\n });\n });\n },\n };\n\n case DialogType.Confirmation:\n return {\n type: 'confirmation',\n content,\n\n ok: async () => {\n await page.evaluate(() => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload: true,\n });\n });\n },\n\n cancel: async () => {\n await page.evaluate(() => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload: false,\n });\n });\n },\n };\n\n case DialogType.Prompt:\n return {\n type: 'prompt',\n content,\n\n ok: async (value) => {\n await page.evaluate((payload) => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload,\n });\n }, value);\n },\n\n cancel: async () => {\n await page.evaluate(() => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload: null,\n });\n });\n },\n };\n\n default:\n throw new Error(`Unknown or unsupported dialog type: ${String(type)}.`);\n }\n}\n\n/**\n * Get the text of the notifications.\n *\n * @param page - The page to get the notifications from.\n * @param requestId - The ID of the request to get the notifications for.\n * @returns The text of the notifications, in order of appearance.\n */\nexport async function getNotifications(page: Page, requestId: string) {\n return await page.evaluate((id) => {\n return window.__SIMULATOR_API__.getNotifications(id);\n }, requestId);\n}\n"],"names":["DialogType","assert","create","SnapOptionsStruct","waitFor","getInterface","page","options","timeout","type","node","content","ui","evaluate","state","window","__SIMULATOR_API__","getState","simulation","message","Alert","ok","dispatch","payload","Confirmation","cancel","Prompt","value","Error","String","getNotifications","requestId","id"],"mappings":"AAAA,SAASA,UAAU,QAAQ,wBAAwB;AACnD,SAASC,MAAM,QAAQ,kBAAkB;AAEzC,SAASC,MAAM,QAAQ,cAAc;AAGrC,SAASC,iBAAiB,QAAQ,YAAY;AAC9C,SAASC,OAAO,QAAQ,aAAa;AAErC;;;;;;;;;CASC,GACD,OAAO,eAAeC,aACpBC,IAAU,EACVC,UAAuB,CAAC,CAAC;IAEzB,MAAM,EAAEC,OAAO,EAAE,GAAGN,OAAOK,SAASJ;IAEpC,MAAM,EAAEM,IAAI,EAAEC,MAAMC,OAAO,EAAE,GAAG,MAAMP,QACpC;QACE,MAAMQ,KAAK,MAAMN,KAAKO,QAAQ,CAAC;YAC7B,MAAMC,QAAQC,OAAOC,iBAAiB,CAACC,QAAQ;YAC/C,OAAOH,MAAMI,UAAU,CAACN,EAAE;QAC5B;QAEAX,OAAOW;QACP,OAAOA;IACT,GACA;QACEJ;QACAW,SAAS;IACX;IAGF,OAAQV;QACN,KAAKT,WAAWoB,KAAK;YACnB,OAAO;gBACLX,MAAM;gBACNE;gBAEAU,IAAI;oBACF,MAAMf,KAAKO,QAAQ,CAAC;wBAClBE,OAAOC,iBAAiB,CAACM,QAAQ,CAAC;4BAChCb,MAAM;4BACNc,SAAS;wBACX;oBACF;gBACF;YACF;QAEF,KAAKvB,WAAWwB,YAAY;YAC1B,OAAO;gBACLf,MAAM;gBACNE;gBAEAU,IAAI;oBACF,MAAMf,KAAKO,QAAQ,CAAC;wBAClBE,OAAOC,iBAAiB,CAACM,QAAQ,CAAC;4BAChCb,MAAM;4BACNc,SAAS;wBACX;oBACF;gBACF;gBAEAE,QAAQ;oBACN,MAAMnB,KAAKO,QAAQ,CAAC;wBAClBE,OAAOC,iBAAiB,CAACM,QAAQ,CAAC;4BAChCb,MAAM;4BACNc,SAAS;wBACX;oBACF;gBACF;YACF;QAEF,KAAKvB,WAAW0B,MAAM;YACpB,OAAO;gBACLjB,MAAM;gBACNE;gBAEAU,IAAI,OAAOM;oBACT,MAAMrB,KAAKO,QAAQ,CAAC,CAACU;wBACnBR,OAAOC,iBAAiB,CAACM,QAAQ,CAAC;4BAChCb,MAAM;4BACNc;wBACF;oBACF,GAAGI;gBACL;gBAEAF,QAAQ;oBACN,MAAMnB,KAAKO,QAAQ,CAAC;wBAClBE,OAAOC,iBAAiB,CAACM,QAAQ,CAAC;4BAChCb,MAAM;4BACNc,SAAS;wBACX;oBACF;gBACF;YACF;QAEF;YACE,MAAM,IAAIK,MAAM,CAAC,oCAAoC,EAAEC,OAAOpB,MAAM,CAAC,CAAC;IAC1E;AACF;AAEA;;;;;;CAMC,GACD,OAAO,eAAeqB,iBAAiBxB,IAAU,EAAEyB,SAAiB;IAClE,OAAO,MAAMzB,KAAKO,QAAQ,CAAC,CAACmB;QAC1B,OAAOjB,OAAOC,iBAAiB,CAACc,gBAAgB,CAACE;IACnD,GAAGD;AACL"}
|
|
1
|
+
{"version":3,"sources":["../../../src/internals/interface.ts"],"sourcesContent":["import { DialogType } from '@metamask/rpc-methods';\nimport { assert } from '@metamask/utils';\nimport type { Page } from 'puppeteer';\nimport { create } from 'superstruct';\n\nimport type { SnapInterface, SnapOptions } from '../types';\nimport { SnapOptionsStruct } from './structs';\nimport { waitFor } from './wait-for';\n\n/**\n * Get the current snap user interface (i.e., dialog). This will throw an error\n * if the snap does not show a user interface within the timeout.\n *\n * @param page - The page to get the interface from.\n * @param options - The options to use.\n * @param options.timeout - The timeout in milliseconds to use. Defaults to\n * `1000`.\n * @returns The user interface object.\n */\nexport async function getInterface(\n page: Page,\n options: SnapOptions = {},\n): Promise<SnapInterface> {\n const { timeout } = create(options, SnapOptionsStruct);\n\n const { type, node: content } = await waitFor(\n async () => {\n const ui = await page.evaluate(() => {\n const state = window.__SIMULATOR_API__.getState();\n return state.simulation.ui;\n });\n\n assert(ui);\n return ui;\n },\n {\n timeout,\n message: 'Timed out waiting for snap interface to be shown.',\n },\n );\n\n switch (type) {\n case DialogType.Alert:\n return {\n type: 'alert',\n content,\n\n ok: async () => {\n await page.evaluate(() => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload: null,\n });\n });\n },\n };\n\n case DialogType.Confirmation:\n return {\n type: 'confirmation',\n content,\n\n ok: async () => {\n await page.evaluate(() => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload: true,\n });\n });\n },\n\n cancel: async () => {\n await page.evaluate(() => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload: false,\n });\n });\n },\n };\n\n case DialogType.Prompt:\n return {\n type: 'prompt',\n content,\n\n ok: async (value) => {\n await page.evaluate((payload) => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload,\n });\n }, value);\n },\n\n cancel: async () => {\n await page.evaluate(() => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/resolveUserInterface',\n payload: null,\n });\n });\n },\n };\n\n default:\n throw new Error(`Unknown or unsupported dialog type: ${String(type)}.`);\n }\n}\n\n/**\n * Get the text of the notifications.\n *\n * @param page - The page to get the notifications from.\n * @param requestId - The ID of the request to get the notifications for.\n * @returns The text of the notifications, in order of appearance.\n */\nexport async function getNotifications(page: Page, requestId: string) {\n return await page.evaluate((id) => {\n return window.__SIMULATOR_API__.getNotifications(id);\n }, requestId);\n}\n"],"names":["DialogType","assert","create","SnapOptionsStruct","waitFor","getInterface","page","options","timeout","type","node","content","ui","evaluate","state","window","__SIMULATOR_API__","getState","simulation","message","Alert","ok","dispatch","payload","Confirmation","cancel","Prompt","value","Error","String","getNotifications","requestId","id"],"mappings":"AAAA,SAASA,UAAU,QAAQ,wBAAwB;AACnD,SAASC,MAAM,QAAQ,kBAAkB;AAEzC,SAASC,MAAM,QAAQ,cAAc;AAGrC,SAASC,iBAAiB,QAAQ,YAAY;AAC9C,SAASC,OAAO,QAAQ,aAAa;AAErC;;;;;;;;;CASC,GACD,OAAO,eAAeC,aACpBC,IAAU,EACVC,UAAuB,CAAC,CAAC;IAEzB,MAAM,EAAEC,OAAO,EAAE,GAAGN,OAAOK,SAASJ;IAEpC,MAAM,EAAEM,IAAI,EAAEC,MAAMC,OAAO,EAAE,GAAG,MAAMP,QACpC;QACE,MAAMQ,KAAK,MAAMN,KAAKO,QAAQ,CAAC;YAC7B,MAAMC,QAAQC,OAAOC,iBAAiB,CAACC,QAAQ;YAC/C,OAAOH,MAAMI,UAAU,CAACN,EAAE;QAC5B;QAEAX,OAAOW;QACP,OAAOA;IACT,GACA;QACEJ;QACAW,SAAS;IACX;IAGF,OAAQV;QACN,KAAKT,WAAWoB,KAAK;YACnB,OAAO;gBACLX,MAAM;gBACNE;gBAEAU,IAAI;oBACF,MAAMf,KAAKO,QAAQ,CAAC;wBAClBE,OAAOC,iBAAiB,CAACM,QAAQ,CAAC;4BAChCb,MAAM;4BACNc,SAAS;wBACX;oBACF;gBACF;YACF;QAEF,KAAKvB,WAAWwB,YAAY;YAC1B,OAAO;gBACLf,MAAM;gBACNE;gBAEAU,IAAI;oBACF,MAAMf,KAAKO,QAAQ,CAAC;wBAClBE,OAAOC,iBAAiB,CAACM,QAAQ,CAAC;4BAChCb,MAAM;4BACNc,SAAS;wBACX;oBACF;gBACF;gBAEAE,QAAQ;oBACN,MAAMnB,KAAKO,QAAQ,CAAC;wBAClBE,OAAOC,iBAAiB,CAACM,QAAQ,CAAC;4BAChCb,MAAM;4BACNc,SAAS;wBACX;oBACF;gBACF;YACF;QAEF,KAAKvB,WAAW0B,MAAM;YACpB,OAAO;gBACLjB,MAAM;gBACNE;gBAEAU,IAAI,OAAOM;oBACT,MAAMrB,KAAKO,QAAQ,CAAC,CAACU;wBACnBR,OAAOC,iBAAiB,CAACM,QAAQ,CAAC;4BAChCb,MAAM;4BACNc;wBACF;oBACF,GAAGI;gBACL;gBAEAF,QAAQ;oBACN,MAAMnB,KAAKO,QAAQ,CAAC;wBAClBE,OAAOC,iBAAiB,CAACM,QAAQ,CAAC;4BAChCb,MAAM;4BACNc,SAAS;wBACX;oBACF;gBACF;YACF;QAEF;YACE,MAAM,IAAIK,MAAM,CAAC,oCAAoC,EAAEC,OAAOpB,MAAM,CAAC,CAAC;IAC1E;AACF;AAEA;;;;;;CAMC,GACD,OAAO,eAAeqB,iBAAiBxB,IAAU,EAAEyB,SAAiB;IAClE,OAAO,MAAMzB,KAAKO,QAAQ,CAAC,CAACmB;QAC1B,OAAOjB,OAAOC,iBAAiB,CAACc,gBAAgB,CAACE;IACnD,GAAGD;AACL"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/internals/network.ts"],"sourcesContent":["import { JSON_RPC_ENDPOINT } from '@metamask/snaps-simulator';\nimport { createModuleLogger, UnsafeJsonStruct } from '@metamask/utils';\nimport { Page, HTTPRequest } from 'puppeteer';\nimport {\n assign,\n boolean,\n create,\n defaulted,\n Infer,\n number,\n object,\n optional,\n record,\n regexp,\n string,\n Struct,\n union,\n unknown,\n func,\n} from 'superstruct';\n\nimport { DeepPartial } from '../types';\nimport { rootLogger } from './logger';\n\n/**\n * The default headers to use for mocked responses. These headers are used to\n * enable CORS.\n */\nconst DEFAULT_HEADERS = {\n /* eslint-disable @typescript-eslint/naming-convention */\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Credentials': 'true',\n 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',\n 'Access-Control-Allow-Headers':\n 'Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers',\n /* eslint-enable @typescript-eslint/naming-convention */\n};\n\nconst log = createModuleLogger(rootLogger, 'network');\n\nexport type Unmock = () => Promise<void>;\n\nexport type Mock = {\n /**\n * A function that can be used to unmock the URL.\n */\n unmock: Unmock;\n};\n\n/**\n * A function that can return `true` if the given request should be mocked, or\n * false if not.\n *\n * @param request - The request to check.\n * @returns Whether to mock the request.\n */\nexport type ConditionFunction = (request: HTTPRequest) => boolean;\n\nconst MockOptionsBaseStruct = object({\n response: defaulted(\n object({\n status: defaulted(number(), 200),\n headers: defaulted(record(string(), unknown()), DEFAULT_HEADERS),\n contentType: defaulted(string(), 'text/plain'),\n\n // Note: We default to a newline here, because the fetch request never\n // resolves if the body is empty.\n body: defaulted(string(), '\\n'),\n }),\n {},\n ),\n});\n\nconst MockOptionsUrlStruct = object({\n url: union([string(), regexp()]),\n partial: optional(boolean()),\n});\n\nconst MockOptionsConditionStruct = object({\n condition: func() as unknown as Struct<ConditionFunction, null>,\n});\n\nexport const MockOptionsStruct = union([\n assign(MockOptionsBaseStruct, MockOptionsUrlStruct),\n assign(MockOptionsBaseStruct, MockOptionsConditionStruct),\n]);\n\n/**\n * The options for the network mocking.\n *\n * @property url - The URL to mock. If a string is provided, the URL will be\n * matched exactly. If a RegExp is provided, the URL will be matched against it.\n * This option is incompatible with the `condition` option.\n * @property partial - If enabled, the request will be mocked if the URL starts\n * with the given URL. This option is ignored if a RegExp is provided to the\n * `url` option. This option is incompatible with the `condition` option.\n * @property condition - A function which gets the {@link HTTPRequest} as\n * parameter and returns a boolean to indicate whether the response should be\n * mocked or not. This option is incompatible with the `url` and `partial`\n * options.\n * @property response - The response to send for the request.\n * @property response.status - The status code to send for the response.\n * Defaults to `200`.\n * @property response.headers - The headers to send for the response. Defaults\n * to headers that enable CORS.\n * @property response.contentType - The content type to send for the response.\n * Defaults to `text/plain`.\n */\nexport type MockOptions = Infer<typeof MockOptionsStruct>;\n\n/**\n * Check if the given URL matches the given request, or if the condition\n * function returns `true`.\n *\n * @param request - The request to check.\n * @param options - The options for the network mocking.\n * @returns Whether the URL matches the request.\n */\nfunction matches(request: HTTPRequest, options: MockOptions) {\n if ('url' in options) {\n const { url, partial } = options;\n if (typeof url === 'string') {\n if (partial) {\n return request.url().startsWith(url);\n }\n\n return url === request.url();\n }\n\n return url.test(request.url());\n }\n\n const { condition } = options;\n return condition(request);\n}\n\n/**\n * Enable network mocking for the given page, and all its sub-frames.\n *\n * @param page - The page to enable network mocking on.\n * @param options - The options for the network mocking.\n * @returns A {@link Mock} object, with an `unmock` function.\n */\nexport async function mock(\n page: Page,\n options: DeepPartial<MockOptions>,\n): Promise<Mock> {\n await page.setRequestInterception(true);\n\n const parsedOptions = create(options, MockOptionsStruct);\n\n /**\n * The mock handler.\n *\n * @param request - The request to handle.\n */\n function handler(request: HTTPRequest) {\n // If the request is already handled, Puppeteer will throw an error if we\n // try to continue the request.\n if (request.isInterceptResolutionHandled()) {\n return;\n }\n\n if (!matches(request, parsedOptions)) {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n request.continue();\n return;\n }\n\n log('Mocking request to %s', request.url());\n\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n request.respond(parsedOptions.response);\n }\n\n /**\n * Unmock the page.\n */\n async function unmock() {\n await page.setRequestInterception(false);\n page.off('request', handler);\n }\n\n page.on('request', handler);\n\n return {\n unmock,\n };\n}\n\nconst MockJsonRpcOptionsStruct = object({\n method: string(),\n result: UnsafeJsonStruct,\n});\n\nexport type MockJsonRpcOptions = Infer<typeof MockJsonRpcOptionsStruct>;\n\n/**\n * Mock an Ethereum JSON-RPC request. This intercepts all requests to the\n * Ethereum provider, and returns the `result` instead.\n *\n * @param page - The page to enable network JSON-RPC mocking on.\n * @param options - The options for the JSON-RPC mock.\n * @param options.method - The JSON-RPC method to mock. Any other methods will be\n * forwarded to the provider.\n * @param options.result - The JSON response to return.\n * @returns A {@link Mock} object, with an `unmock` function.\n */\nexport async function mockJsonRpc(\n page: Page,\n { method, result }: MockJsonRpcOptions,\n) {\n return await mock(page, {\n condition: (request: HTTPRequest) => {\n if (request.url() !== JSON_RPC_ENDPOINT) {\n return false;\n }\n\n const body = request.postData();\n if (!body) {\n return false;\n }\n\n try {\n const json = JSON.parse(body);\n return json.method === method;\n } catch (error) {\n log(\n `Unable to mock \"${method}\" request to Ethereum provider: %s`,\n error.message,\n );\n return false;\n }\n },\n response: {\n status: 200,\n contentType: 'application/json',\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n result,\n }),\n },\n });\n}\n"],"names":["JSON_RPC_ENDPOINT","createModuleLogger","UnsafeJsonStruct","assign","boolean","create","defaulted","number","object","optional","record","regexp","string","union","unknown","func","rootLogger","DEFAULT_HEADERS","log","MockOptionsBaseStruct","response","status","headers","contentType","body","MockOptionsUrlStruct","url","partial","MockOptionsConditionStruct","condition","MockOptionsStruct","matches","request","options","startsWith","test","mock","page","setRequestInterception","parsedOptions","handler","isInterceptResolutionHandled","continue","respond","unmock","off","on","MockJsonRpcOptionsStruct","method","result","mockJsonRpc","postData","json","JSON","parse","error","message","stringify","jsonrpc","id"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/internals/network.ts"],"sourcesContent":["import { JSON_RPC_ENDPOINT } from '@metamask/snaps-simulator';\nimport { createModuleLogger, UnsafeJsonStruct } from '@metamask/utils';\nimport type { Page, HTTPRequest } from 'puppeteer';\nimport type { Infer, Struct } from 'superstruct';\nimport {\n assign,\n boolean,\n create,\n defaulted,\n number,\n object,\n optional,\n record,\n regexp,\n string,\n union,\n unknown,\n func,\n} from 'superstruct';\n\nimport type { DeepPartial } from '../types';\nimport { rootLogger } from './logger';\n\n/**\n * The default headers to use for mocked responses. These headers are used to\n * enable CORS.\n */\nconst DEFAULT_HEADERS = {\n /* eslint-disable @typescript-eslint/naming-convention */\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Credentials': 'true',\n 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',\n 'Access-Control-Allow-Headers':\n 'Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers',\n /* eslint-enable @typescript-eslint/naming-convention */\n};\n\nconst log = createModuleLogger(rootLogger, 'network');\n\nexport type Unmock = () => Promise<void>;\n\nexport type Mock = {\n /**\n * A function that can be used to unmock the URL.\n */\n unmock: Unmock;\n};\n\n/**\n * A function that can return `true` if the given request should be mocked, or\n * false if not.\n *\n * @param request - The request to check.\n * @returns Whether to mock the request.\n */\nexport type ConditionFunction = (request: HTTPRequest) => boolean;\n\nconst MockOptionsBaseStruct = object({\n response: defaulted(\n object({\n status: defaulted(number(), 200),\n headers: defaulted(record(string(), unknown()), DEFAULT_HEADERS),\n contentType: defaulted(string(), 'text/plain'),\n\n // Note: We default to a newline here, because the fetch request never\n // resolves if the body is empty.\n body: defaulted(string(), '\\n'),\n }),\n {},\n ),\n});\n\nconst MockOptionsUrlStruct = object({\n url: union([string(), regexp()]),\n partial: optional(boolean()),\n});\n\nconst MockOptionsConditionStruct = object({\n condition: func() as unknown as Struct<ConditionFunction, null>,\n});\n\nexport const MockOptionsStruct = union([\n assign(MockOptionsBaseStruct, MockOptionsUrlStruct),\n assign(MockOptionsBaseStruct, MockOptionsConditionStruct),\n]);\n\n/**\n * The options for the network mocking.\n *\n * @property url - The URL to mock. If a string is provided, the URL will be\n * matched exactly. If a RegExp is provided, the URL will be matched against it.\n * This option is incompatible with the `condition` option.\n * @property partial - If enabled, the request will be mocked if the URL starts\n * with the given URL. This option is ignored if a RegExp is provided to the\n * `url` option. This option is incompatible with the `condition` option.\n * @property condition - A function which gets the {@link HTTPRequest} as\n * parameter and returns a boolean to indicate whether the response should be\n * mocked or not. This option is incompatible with the `url` and `partial`\n * options.\n * @property response - The response to send for the request.\n * @property response.status - The status code to send for the response.\n * Defaults to `200`.\n * @property response.headers - The headers to send for the response. Defaults\n * to headers that enable CORS.\n * @property response.contentType - The content type to send for the response.\n * Defaults to `text/plain`.\n */\nexport type MockOptions = Infer<typeof MockOptionsStruct>;\n\n/**\n * Check if the given URL matches the given request, or if the condition\n * function returns `true`.\n *\n * @param request - The request to check.\n * @param options - The options for the network mocking.\n * @returns Whether the URL matches the request.\n */\nfunction matches(request: HTTPRequest, options: MockOptions) {\n if ('url' in options) {\n const { url, partial } = options;\n if (typeof url === 'string') {\n if (partial) {\n return request.url().startsWith(url);\n }\n\n return url === request.url();\n }\n\n return url.test(request.url());\n }\n\n const { condition } = options;\n return condition(request);\n}\n\n/**\n * Enable network mocking for the given page, and all its sub-frames.\n *\n * @param page - The page to enable network mocking on.\n * @param options - The options for the network mocking.\n * @returns A {@link Mock} object, with an `unmock` function.\n */\nexport async function mock(\n page: Page,\n options: DeepPartial<MockOptions>,\n): Promise<Mock> {\n await page.setRequestInterception(true);\n\n const parsedOptions = create(options, MockOptionsStruct);\n\n /**\n * The mock handler.\n *\n * @param request - The request to handle.\n */\n function handler(request: HTTPRequest) {\n // If the request is already handled, Puppeteer will throw an error if we\n // try to continue the request.\n if (request.isInterceptResolutionHandled()) {\n return;\n }\n\n if (!matches(request, parsedOptions)) {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n request.continue();\n return;\n }\n\n log('Mocking request to %s', request.url());\n\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n request.respond(parsedOptions.response);\n }\n\n /**\n * Unmock the page.\n */\n async function unmock() {\n await page.setRequestInterception(false);\n page.off('request', handler);\n }\n\n page.on('request', handler);\n\n return {\n unmock,\n };\n}\n\nconst MockJsonRpcOptionsStruct = object({\n method: string(),\n result: UnsafeJsonStruct,\n});\n\nexport type MockJsonRpcOptions = Infer<typeof MockJsonRpcOptionsStruct>;\n\n/**\n * Mock an Ethereum JSON-RPC request. This intercepts all requests to the\n * Ethereum provider, and returns the `result` instead.\n *\n * @param page - The page to enable network JSON-RPC mocking on.\n * @param options - The options for the JSON-RPC mock.\n * @param options.method - The JSON-RPC method to mock. Any other methods will be\n * forwarded to the provider.\n * @param options.result - The JSON response to return.\n * @returns A {@link Mock} object, with an `unmock` function.\n */\nexport async function mockJsonRpc(\n page: Page,\n { method, result }: MockJsonRpcOptions,\n) {\n return await mock(page, {\n condition: (request: HTTPRequest) => {\n if (request.url() !== JSON_RPC_ENDPOINT) {\n return false;\n }\n\n const body = request.postData();\n if (!body) {\n return false;\n }\n\n try {\n const json = JSON.parse(body);\n return json.method === method;\n } catch (error) {\n log(\n `Unable to mock \"${method}\" request to Ethereum provider: %s`,\n error.message,\n );\n return false;\n }\n },\n response: {\n status: 200,\n contentType: 'application/json',\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n result,\n }),\n },\n });\n}\n"],"names":["JSON_RPC_ENDPOINT","createModuleLogger","UnsafeJsonStruct","assign","boolean","create","defaulted","number","object","optional","record","regexp","string","union","unknown","func","rootLogger","DEFAULT_HEADERS","log","MockOptionsBaseStruct","response","status","headers","contentType","body","MockOptionsUrlStruct","url","partial","MockOptionsConditionStruct","condition","MockOptionsStruct","matches","request","options","startsWith","test","mock","page","setRequestInterception","parsedOptions","handler","isInterceptResolutionHandled","continue","respond","unmock","off","on","MockJsonRpcOptionsStruct","method","result","mockJsonRpc","postData","json","JSON","parse","error","message","stringify","jsonrpc","id"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/internals/request.ts"],"sourcesContent":["import { Component } from '@metamask/snaps-ui';\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/internals/request.ts"],"sourcesContent":["import type { Component } from '@metamask/snaps-ui';\nimport type { SnapRpcHookArgs } from '@metamask/snaps-utils';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport {\n assert,\n createModuleLogger,\n hasProperty,\n isPlainObject,\n} from '@metamask/utils';\nimport { getDocument, queries } from 'pptr-testing-library';\nimport type { Page } from 'puppeteer';\nimport { create } from 'superstruct';\n\nimport type {\n CronjobOptions,\n RequestOptions,\n SnapRequest,\n SnapResponse,\n TransactionOptions,\n} from '../types';\nimport { getInterface, getNotifications } from './interface';\nimport { rootLogger } from './logger';\nimport { TransactionOptionsStruct } from './structs';\nimport { waitForResponse } from './wait-for';\n\nconst log = createModuleLogger(rootLogger, 'request');\n\n/**\n * Send a request to the snap.\n *\n * @param page - The page to send the request from.\n * @param args - The request arguments.\n * @returns The request ID.\n */\nasync function sendRequest(page: Page, args: SnapRpcHookArgs) {\n const document = await getDocument(page);\n const button = await queries.getByTestId(\n document,\n `navigation-${args.handler}`,\n );\n\n // Navigate to the request handler page.\n await button.click();\n\n return await page.evaluate((payload) => {\n window.__SIMULATOR_API__.dispatch({\n type: 'simulation/sendRequest',\n payload,\n });\n\n return window.__SIMULATOR_API__.getRequestId();\n }, args);\n}\n\n/**\n * Send a request to the snap.\n *\n * @param page - The page to send the request from.\n * @param options - The request options.\n * @param options.origin - The origin of the request. Defaults to `metamask.io`.\n * @param handler - The handler to use. Defaults to `onRpcRequest`.\n * @returns The response.\n */\nexport function request(\n page: Page,\n { origin = 'metamask.io', ...options }: RequestOptions,\n handler:\n | HandlerType.OnRpcRequest\n | HandlerType.OnCronjob = HandlerType.OnRpcRequest,\n) {\n const doRequest = async (): Promise<SnapResponse> => {\n const args: SnapRpcHookArgs = {\n origin,\n handler,\n request: {\n jsonrpc: '2.0',\n id: 1,\n ...options,\n },\n };\n\n log('Sending request %o', args);\n\n const promise = waitForResponse(page, handler);\n const id = await sendRequest(page, args);\n const response = await promise;\n\n log('Received response %o', response);\n\n const notifications = await getNotifications(page, id);\n\n return { id, response, notifications };\n };\n\n // This is a bit hacky, but it allows us to add the `getInterface` method\n // to the response promise.\n const response = doRequest() as SnapRequest;\n\n response.getInterface = async (getInterfaceOptions) => {\n return await getInterface(page, getInterfaceOptions);\n };\n\n return response;\n}\n\n/**\n * Send a transaction to the snap.\n *\n * @param page - The page to send the transaction from.\n * @param options - The transaction options.\n * @returns The response.\n */\nexport async function sendTransaction(\n page: Page,\n options: Partial<TransactionOptions>,\n) {\n const {\n origin: transactionOrigin,\n chainId,\n ...transaction\n } = create(options, TransactionOptionsStruct);\n\n const args: SnapRpcHookArgs = {\n origin: '',\n handler: HandlerType.OnTransaction,\n request: {\n jsonrpc: '2.0',\n method: '',\n params: {\n chainId,\n transaction,\n transactionOrigin,\n },\n },\n };\n\n log('Sending transaction %o', args);\n\n const promise = waitForResponse(page, HandlerType.OnTransaction);\n const id = await sendRequest(page, args);\n const response = await promise;\n\n log('Received response %o', response);\n\n if (hasProperty(response, 'error')) {\n return { id, response, notifications: [] };\n }\n\n assert(isPlainObject(response.result));\n assert(hasProperty(response.result, 'content'));\n\n return {\n id,\n response,\n notifications: [],\n content: response.result.content as Component,\n };\n}\n\n/**\n * Run a cronjob.\n *\n * @param page - The page to run the cronjob from.\n * @param options - The request options.\n * @returns The response.\n */\nexport function runCronjob(page: Page, options: CronjobOptions) {\n return request(page, options, HandlerType.OnCronjob);\n}\n"],"names":["HandlerType","assert","createModuleLogger","hasProperty","isPlainObject","getDocument","queries","create","getInterface","getNotifications","rootLogger","TransactionOptionsStruct","waitForResponse","log","sendRequest","page","args","document","button","getByTestId","handler","click","evaluate","payload","window","__SIMULATOR_API__","dispatch","type","getRequestId","request","origin","options","OnRpcRequest","doRequest","jsonrpc","id","promise","response","notifications","getInterfaceOptions","sendTransaction","transactionOrigin","chainId","transaction","OnTransaction","method","params","result","content","runCronjob","OnCronjob"],"mappings":"AAEA,SAASA,WAAW,QAAQ,wBAAwB;AACpD,SACEC,MAAM,EACNC,kBAAkB,EAClBC,WAAW,EACXC,aAAa,QACR,kBAAkB;AACzB,SAASC,WAAW,EAAEC,OAAO,QAAQ,uBAAuB;AAE5D,SAASC,MAAM,QAAQ,cAAc;AASrC,SAASC,YAAY,EAAEC,gBAAgB,QAAQ,cAAc;AAC7D,SAASC,UAAU,QAAQ,WAAW;AACtC,SAASC,wBAAwB,QAAQ,YAAY;AACrD,SAASC,eAAe,QAAQ,aAAa;AAE7C,MAAMC,MAAMX,mBAAmBQ,YAAY;AAE3C;;;;;;CAMC,GACD,eAAeI,YAAYC,IAAU,EAAEC,IAAqB;IAC1D,MAAMC,WAAW,MAAMZ,YAAYU;IACnC,MAAMG,SAAS,MAAMZ,QAAQa,WAAW,CACtCF,UACA,CAAC,WAAW,EAAED,KAAKI,OAAO,CAAC,CAAC;IAG9B,wCAAwC;IACxC,MAAMF,OAAOG,KAAK;IAElB,OAAO,MAAMN,KAAKO,QAAQ,CAAC,CAACC;QAC1BC,OAAOC,iBAAiB,CAACC,QAAQ,CAAC;YAChCC,MAAM;YACNJ;QACF;QAEA,OAAOC,OAAOC,iBAAiB,CAACG,YAAY;IAC9C,GAAGZ;AACL;AAEA;;;;;;;;CAQC,GACD,OAAO,SAASa,QACdd,IAAU,EACV,EAAEe,SAAS,aAAa,EAAE,GAAGC,SAAyB,EACtDX,UAE4BpB,YAAYgC,YAAY;IAEpD,MAAMC,YAAY;QAChB,MAAMjB,OAAwB;YAC5Bc;YACAV;YACAS,SAAS;gBACPK,SAAS;gBACTC,IAAI;gBACJ,GAAGJ,OAAO;YACZ;QACF;QAEAlB,IAAI,sBAAsBG;QAE1B,MAAMoB,UAAUxB,gBAAgBG,MAAMK;QACtC,MAAMe,KAAK,MAAMrB,YAAYC,MAAMC;QACnC,MAAMqB,WAAW,MAAMD;QAEvBvB,IAAI,wBAAwBwB;QAE5B,MAAMC,gBAAgB,MAAM7B,iBAAiBM,MAAMoB;QAEnD,OAAO;YAAEA;YAAIE;YAAUC;QAAc;IACvC;IAEA,yEAAyE;IACzE,2BAA2B;IAC3B,MAAMD,WAAWJ;IAEjBI,SAAS7B,YAAY,GAAG,OAAO+B;QAC7B,OAAO,MAAM/B,aAAaO,MAAMwB;IAClC;IAEA,OAAOF;AACT;AAEA;;;;;;CAMC,GACD,OAAO,eAAeG,gBACpBzB,IAAU,EACVgB,OAAoC;IAEpC,MAAM,EACJD,QAAQW,iBAAiB,EACzBC,OAAO,EACP,GAAGC,aACJ,GAAGpC,OAAOwB,SAASpB;IAEpB,MAAMK,OAAwB;QAC5Bc,QAAQ;QACRV,SAASpB,YAAY4C,aAAa;QAClCf,SAAS;YACPK,SAAS;YACTW,QAAQ;YACRC,QAAQ;gBACNJ;gBACAC;gBACAF;YACF;QACF;IACF;IAEA5B,IAAI,0BAA0BG;IAE9B,MAAMoB,UAAUxB,gBAAgBG,MAAMf,YAAY4C,aAAa;IAC/D,MAAMT,KAAK,MAAMrB,YAAYC,MAAMC;IACnC,MAAMqB,WAAW,MAAMD;IAEvBvB,IAAI,wBAAwBwB;IAE5B,IAAIlC,YAAYkC,UAAU,UAAU;QAClC,OAAO;YAAEF;YAAIE;YAAUC,eAAe,EAAE;QAAC;IAC3C;IAEArC,OAAOG,cAAciC,SAASU,MAAM;IACpC9C,OAAOE,YAAYkC,SAASU,MAAM,EAAE;IAEpC,OAAO;QACLZ;QACAE;QACAC,eAAe,EAAE;QACjBU,SAASX,SAASU,MAAM,CAACC,OAAO;IAClC;AACF;AAEA;;;;;;CAMC,GACD,OAAO,SAASC,WAAWlC,IAAU,EAAEgB,OAAuB;IAC5D,OAAOF,QAAQd,MAAMgB,SAAS/B,YAAYkD,SAAS;AACrD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/internals/server.ts"],"sourcesContent":["import {\n assertIsSnapManifest,\n isDirectory,\n isFile,\n
|
|
1
|
+
{"version":3,"sources":["../../../src/internals/server.ts"],"sourcesContent":["import type { SnapManifest } from '@metamask/snaps-utils';\nimport {\n assertIsSnapManifest,\n isDirectory,\n isFile,\n} from '@metamask/snaps-utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport express from 'express';\nimport { promises as fs } from 'fs';\nimport type { Server } from 'http';\nimport { createServer } from 'http';\nimport { resolve as pathResolve, dirname } from 'path';\n\nimport type { SnapsEnvironmentOptions } from '../options';\nimport { rootLogger } from './logger';\n\nconst SNAPS_EXECUTION_ENVIRONMENTS_PATH = pathResolve(\n dirname(\n require.resolve('@metamask/snaps-execution-environments/package.json'),\n ),\n 'dist',\n 'browserify',\n 'iframe',\n);\n\nconst SNAPS_SIMULATOR_PATH = pathResolve(\n dirname(require.resolve('@metamask/snaps-simulator/package.json')),\n 'dist',\n 'webpack',\n 'test',\n);\n\nexport type ServerOptions = Required<\n // We need a double `Required` for the type to be inferred correctly.\n Required<SnapsEnvironmentOptions>['server']\n>;\n\n/**\n * Check that:\n *\n * - The root directory exists.\n * - The root directory contains a `snap.manifest.json` file.\n * - The file path in the manifest exists.\n *\n * @param root - The root directory.\n * @throws If any of the checks fail.\n */\nasync function assertRoot(root: string) {\n if (!root) {\n throw new Error('You must specify a root directory.');\n }\n\n if (!(await isDirectory(root, false))) {\n throw new Error(`Root directory \"${root}\" is not a directory.`);\n }\n\n const manifestPath = pathResolve(root, 'snap.manifest.json');\n const manifest: SnapManifest = await fs\n .readFile(manifestPath, 'utf8')\n .then(JSON.parse);\n\n assertIsSnapManifest(manifest);\n const filePath = pathResolve(root, manifest.source.location.npm.filePath);\n\n if (!(await isFile(filePath))) {\n throw new Error(\n `File \"${filePath}\" does not exist, or is not a file. Did you forget to build your snap?`,\n );\n }\n}\n\n/**\n * Start an HTTP server on `localhost` with a random port. This is used to serve\n * the static files for the environment.\n *\n * @param options - The options to use.\n * @param options.port - The port to use for the server.\n * @param options.root - The root directory to serve from the server.\n * @returns The HTTP server.\n */\nexport async function startServer(options: ServerOptions) {\n await assertRoot(options.root);\n\n const log = createModuleLogger(rootLogger, 'server');\n const app = express();\n\n app.use((_request, response, next) => {\n response.header('Access-Control-Allow-Origin', '*');\n response.header('Access-Control-Allow-Credentials', 'true');\n response.header('Access-Control-Allow-Methods', 'GET, OPTIONS');\n response.header('Access-Control-Allow-Headers', 'Content-Type');\n\n next();\n });\n\n app.use('/environment', express.static(SNAPS_EXECUTION_ENVIRONMENTS_PATH));\n app.use('/simulator', express.static(SNAPS_SIMULATOR_PATH));\n app.use(express.static(pathResolve(process.cwd(), options.root)));\n\n const server = createServer(app);\n return await new Promise<Server>((resolve, reject) => {\n server.listen(options.port, () => {\n resolve(server);\n });\n\n server.on('error', (error) => {\n log(error);\n reject(error);\n });\n });\n}\n"],"names":["assertIsSnapManifest","isDirectory","isFile","createModuleLogger","express","promises","fs","createServer","resolve","pathResolve","dirname","rootLogger","SNAPS_EXECUTION_ENVIRONMENTS_PATH","require","SNAPS_SIMULATOR_PATH","assertRoot","root","Error","manifestPath","manifest","readFile","then","JSON","parse","filePath","source","location","npm","startServer","options","log","app","use","_request","response","next","header","static","process","cwd","server","Promise","reject","listen","port","on","error"],"mappings":"AACA,SACEA,oBAAoB,EACpBC,WAAW,EACXC,MAAM,QACD,wBAAwB;AAC/B,SAASC,kBAAkB,QAAQ,kBAAkB;AACrD,OAAOC,aAAa,UAAU;AAC9B,SAASC,YAAYC,EAAE,QAAQ,KAAK;AAEpC,SAASC,YAAY,QAAQ,OAAO;AACpC,SAASC,WAAWC,WAAW,EAAEC,OAAO,QAAQ,OAAO;AAGvD,SAASC,UAAU,QAAQ,WAAW;AAEtC,MAAMC,oCAAoCH,YACxCC,QACEG,QAAQL,OAAO,CAAC,yDAElB,QACA,cACA;AAGF,MAAMM,uBAAuBL,YAC3BC,QAAQG,QAAQL,OAAO,CAAC,4CACxB,QACA,WACA;AAQF;;;;;;;;;CASC,GACD,eAAeO,WAAWC,IAAY;IACpC,IAAI,CAACA,MAAM;QACT,MAAM,IAAIC,MAAM;IAClB;IAEA,IAAI,CAAE,MAAMhB,YAAYe,MAAM,QAAS;QACrC,MAAM,IAAIC,MAAM,CAAC,gBAAgB,EAAED,KAAK,qBAAqB,CAAC;IAChE;IAEA,MAAME,eAAeT,YAAYO,MAAM;IACvC,MAAMG,WAAyB,MAAMb,GAClCc,QAAQ,CAACF,cAAc,QACvBG,IAAI,CAACC,KAAKC,KAAK;IAElBvB,qBAAqBmB;IACrB,MAAMK,WAAWf,YAAYO,MAAMG,SAASM,MAAM,CAACC,QAAQ,CAACC,GAAG,CAACH,QAAQ;IAExE,IAAI,CAAE,MAAMtB,OAAOsB,WAAY;QAC7B,MAAM,IAAIP,MACR,CAAC,MAAM,EAAEO,SAAS,sEAAsE,CAAC;IAE7F;AACF;AAEA;;;;;;;;CAQC,GACD,OAAO,eAAeI,YAAYC,OAAsB;IACtD,MAAMd,WAAWc,QAAQb,IAAI;IAE7B,MAAMc,MAAM3B,mBAAmBQ,YAAY;IAC3C,MAAMoB,MAAM3B;IAEZ2B,IAAIC,GAAG,CAAC,CAACC,UAAUC,UAAUC;QAC3BD,SAASE,MAAM,CAAC,+BAA+B;QAC/CF,SAASE,MAAM,CAAC,oCAAoC;QACpDF,SAASE,MAAM,CAAC,gCAAgC;QAChDF,SAASE,MAAM,CAAC,gCAAgC;QAEhDD;IACF;IAEAJ,IAAIC,GAAG,CAAC,gBAAgB5B,QAAQiC,MAAM,CAACzB;IACvCmB,IAAIC,GAAG,CAAC,cAAc5B,QAAQiC,MAAM,CAACvB;IACrCiB,IAAIC,GAAG,CAAC5B,QAAQiC,MAAM,CAAC5B,YAAY6B,QAAQC,GAAG,IAAIV,QAAQb,IAAI;IAE9D,MAAMwB,SAASjC,aAAawB;IAC5B,OAAO,MAAM,IAAIU,QAAgB,CAACjC,SAASkC;QACzCF,OAAOG,MAAM,CAACd,QAAQe,IAAI,EAAE;YAC1BpC,QAAQgC;QACV;QAEAA,OAAOK,EAAE,CAAC,SAAS,CAACC;YAClBhB,IAAIgB;YACJJ,OAAOI;QACT;IACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/internals/types.ts"],"sourcesContent":["import { NotificationType } from '@metamask/rpc-methods';\nimport { ApplicationState, Dispatch } from '@metamask/snaps-simulator';\nimport { EnumToUnion } from '@metamask/snaps-utils';\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface Window {\n // This API is injected into the page by the simulator. It allows us to\n // dispatch actions to the simulator, and read the state directly from the\n // Redux store.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n __SIMULATOR_API__: {\n dispatch: Dispatch;\n subscribe: (listener: () => void) => () => void;\n getState: () => ApplicationState;\n getRequestId: () => string;\n getNotifications: (requestId: string) => {\n id: string;\n message: string;\n type: EnumToUnion<NotificationType>;\n }[];\n };\n }\n}\n\nexport {};\n"],"names":[],"mappings":"AAAA,WAyBU"}
|
|
1
|
+
{"version":3,"sources":["../../../src/internals/types.ts"],"sourcesContent":["import type { NotificationType } from '@metamask/rpc-methods';\nimport type { ApplicationState, Dispatch } from '@metamask/snaps-simulator';\nimport type { EnumToUnion } from '@metamask/snaps-utils';\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface Window {\n // This API is injected into the page by the simulator. It allows us to\n // dispatch actions to the simulator, and read the state directly from the\n // Redux store.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n __SIMULATOR_API__: {\n dispatch: Dispatch;\n subscribe: (listener: () => void) => () => void;\n getState: () => ApplicationState;\n getRequestId: () => string;\n getNotifications: (requestId: string) => {\n id: string;\n message: string;\n type: EnumToUnion<NotificationType>;\n }[];\n };\n }\n}\n\nexport {};\n"],"names":[],"mappings":"AAAA,WAyBU"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/internals/wait-for.ts"],"sourcesContent":["import { HandlerType } from '@metamask/snaps-utils';\nimport { assert, createModuleLogger } from '@metamask/utils';\nimport { waitFor as waitForPuppeteer } from 'pptr-testing-library';\nimport { Page } from 'puppeteer';\n\nimport { SnapResponse } from '../types';\nimport { rootLogger } from './logger';\n\nexport type WaitForOptions = {\n /**\n * The timeout in milliseconds.\n */\n timeout?: number;\n\n /**\n * The error message to throw if the condition is not met.\n */\n message?: string;\n};\n\nconst log = createModuleLogger(rootLogger, 'wait-for');\n\n/**\n * Wait for a condition to be true. This is a wrapper around\n * `pptr-testing-library`'s `waitFor` function, with the addition of a custom\n * error message.\n *\n * @param fn - The condition to wait for.\n * @param options - The options.\n * @param options.timeout - The timeout in milliseconds.\n * @param options.message - The error message to throw if the condition is not\n * met.\n * @returns A promise that resolves when the condition is met. The promise\n * resolves to the return value of the condition function.\n */\nexport async function waitFor<Result>(\n fn: () => Promise<Result>,\n { timeout = 3000, message }: WaitForOptions = {},\n) {\n try {\n let result: Result | undefined;\n\n await waitForPuppeteer(\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async () => {\n // Puppeteer's `waitFor` function does not support returning a value\n // from the condition function, so we need to use a variable outside\n // the scope of the function.\n result = await fn();\n },\n {\n timeout,\n },\n );\n\n assert(result !== undefined);\n return result;\n } catch (error) {\n if (message) {\n throw new Error(message);\n }\n\n throw error;\n }\n}\n\n/**\n * Wait for a JSON-RPC response.\n *\n * @param page - The page to wait for the response on.\n * @param type - The type of response to wait for.\n * @returns The JSON-RPC response.\n */\nexport async function waitForResponse(\n page: Page,\n type:\n | HandlerType.OnTransaction\n | HandlerType.OnRpcRequest\n | HandlerType.OnCronjob,\n) {\n log('Waiting for response of type %s.', type);\n\n return await page.evaluate(async (_type) => {\n return new Promise<SnapResponse['response']>((resolve) => {\n window.__SIMULATOR_API__.dispatch({\n type: `${_type}/clearResponse`,\n });\n\n const unsubscribe = window.__SIMULATOR_API__.subscribe(() => {\n const state = window.__SIMULATOR_API__.getState();\n const { pending, response } = state[_type];\n\n if (!pending && response) {\n unsubscribe();\n\n resolve(response);\n }\n });\n });\n }, type);\n}\n"],"names":["assert","createModuleLogger","waitFor","waitForPuppeteer","rootLogger","log","fn","timeout","message","result","undefined","error","Error","waitForResponse","page","type","evaluate","_type","Promise","resolve","window","__SIMULATOR_API__","dispatch","unsubscribe","subscribe","state","getState","pending","response"],"mappings":"AACA,SAASA,MAAM,EAAEC,kBAAkB,QAAQ,kBAAkB;AAC7D,SAASC,WAAWC,gBAAgB,QAAQ,uBAAuB;AAInE,SAASC,UAAU,QAAQ,WAAW;AActC,MAAMC,MAAMJ,mBAAmBG,YAAY;AAE3C;;;;;;;;;;;;CAYC,GACD,OAAO,eAAeF,QACpBI,EAAyB,EACzB,EAAEC,UAAU,IAAI,EAAEC,OAAO,EAAkB,GAAG,CAAC,CAAC;IAEhD,IAAI;QACF,IAAIC;QAEJ,MAAMN,iBACJ,kEAAkE;QAClE;YACE,oEAAoE;YACpE,oEAAoE;YACpE,6BAA6B;YAC7BM,SAAS,MAAMH;QACjB,GACA;YACEC;QACF;QAGFP,OAAOS,WAAWC;QAClB,OAAOD;IACT,EAAE,OAAOE,OAAO;QACd,IAAIH,SAAS;YACX,MAAM,IAAII,MAAMJ;QAClB;QAEA,MAAMG;IACR;AACF;AAEA;;;;;;CAMC,GACD,OAAO,eAAeE,gBACpBC,IAAU,EACVC,IAGyB;IAEzBV,IAAI,oCAAoCU;IAExC,OAAO,MAAMD,KAAKE,QAAQ,CAAC,OAAOC;QAChC,OAAO,IAAIC,QAAkC,CAACC;YAC5CC,OAAOC,iBAAiB,CAACC,QAAQ,CAAC;gBAChCP,MAAM,CAAC,EAAEE,MAAM,cAAc,CAAC;YAChC;YAEA,MAAMM,cAAcH,OAAOC,iBAAiB,CAACG,SAAS,CAAC;gBACrD,MAAMC,QAAQL,OAAOC,iBAAiB,CAACK,QAAQ;gBAC/C,MAAM,EAAEC,OAAO,EAAEC,QAAQ,EAAE,GAAGH,KAAK,CAACR,MAAM;gBAE1C,IAAI,CAACU,WAAWC,UAAU;oBACxBL;oBAEAJ,QAAQS;gBACV;YACF;QACF;IACF,GAAGb;AACL"}
|
|
1
|
+
{"version":3,"sources":["../../../src/internals/wait-for.ts"],"sourcesContent":["import type { HandlerType } from '@metamask/snaps-utils';\nimport { assert, createModuleLogger } from '@metamask/utils';\nimport { waitFor as waitForPuppeteer } from 'pptr-testing-library';\nimport type { Page } from 'puppeteer';\n\nimport type { SnapResponse } from '../types';\nimport { rootLogger } from './logger';\n\nexport type WaitForOptions = {\n /**\n * The timeout in milliseconds.\n */\n timeout?: number;\n\n /**\n * The error message to throw if the condition is not met.\n */\n message?: string;\n};\n\nconst log = createModuleLogger(rootLogger, 'wait-for');\n\n/**\n * Wait for a condition to be true. This is a wrapper around\n * `pptr-testing-library`'s `waitFor` function, with the addition of a custom\n * error message.\n *\n * @param fn - The condition to wait for.\n * @param options - The options.\n * @param options.timeout - The timeout in milliseconds.\n * @param options.message - The error message to throw if the condition is not\n * met.\n * @returns A promise that resolves when the condition is met. The promise\n * resolves to the return value of the condition function.\n */\nexport async function waitFor<Result>(\n fn: () => Promise<Result>,\n { timeout = 3000, message }: WaitForOptions = {},\n) {\n try {\n let result: Result | undefined;\n\n await waitForPuppeteer(\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async () => {\n // Puppeteer's `waitFor` function does not support returning a value\n // from the condition function, so we need to use a variable outside\n // the scope of the function.\n result = await fn();\n },\n {\n timeout,\n },\n );\n\n assert(result !== undefined);\n return result;\n } catch (error) {\n if (message) {\n throw new Error(message);\n }\n\n throw error;\n }\n}\n\n/**\n * Wait for a JSON-RPC response.\n *\n * @param page - The page to wait for the response on.\n * @param type - The type of response to wait for.\n * @returns The JSON-RPC response.\n */\nexport async function waitForResponse(\n page: Page,\n type:\n | HandlerType.OnTransaction\n | HandlerType.OnRpcRequest\n | HandlerType.OnCronjob,\n) {\n log('Waiting for response of type %s.', type);\n\n return await page.evaluate(async (_type) => {\n return new Promise<SnapResponse['response']>((resolve) => {\n window.__SIMULATOR_API__.dispatch({\n type: `${_type}/clearResponse`,\n });\n\n const unsubscribe = window.__SIMULATOR_API__.subscribe(() => {\n const state = window.__SIMULATOR_API__.getState();\n const { pending, response } = state[_type];\n\n if (!pending && response) {\n unsubscribe();\n\n resolve(response);\n }\n });\n });\n }, type);\n}\n"],"names":["assert","createModuleLogger","waitFor","waitForPuppeteer","rootLogger","log","fn","timeout","message","result","undefined","error","Error","waitForResponse","page","type","evaluate","_type","Promise","resolve","window","__SIMULATOR_API__","dispatch","unsubscribe","subscribe","state","getState","pending","response"],"mappings":"AACA,SAASA,MAAM,EAAEC,kBAAkB,QAAQ,kBAAkB;AAC7D,SAASC,WAAWC,gBAAgB,QAAQ,uBAAuB;AAInE,SAASC,UAAU,QAAQ,WAAW;AActC,MAAMC,MAAMJ,mBAAmBG,YAAY;AAE3C;;;;;;;;;;;;CAYC,GACD,OAAO,eAAeF,QACpBI,EAAyB,EACzB,EAAEC,UAAU,IAAI,EAAEC,OAAO,EAAkB,GAAG,CAAC,CAAC;IAEhD,IAAI;QACF,IAAIC;QAEJ,MAAMN,iBACJ,kEAAkE;QAClE;YACE,oEAAoE;YACpE,oEAAoE;YACpE,6BAA6B;YAC7BM,SAAS,MAAMH;QACjB,GACA;YACEC;QACF;QAGFP,OAAOS,WAAWC;QAClB,OAAOD;IACT,EAAE,OAAOE,OAAO;QACd,IAAIH,SAAS;YACX,MAAM,IAAII,MAAMJ;QAClB;QAEA,MAAMG;IACR;AACF;AAEA;;;;;;CAMC,GACD,OAAO,eAAeE,gBACpBC,IAAU,EACVC,IAGyB;IAEzBV,IAAI,oCAAoCU;IAExC,OAAO,MAAMD,KAAKE,QAAQ,CAAC,OAAOC;QAChC,OAAO,IAAIC,QAAkC,CAACC;YAC5CC,OAAOC,iBAAiB,CAACC,QAAQ,CAAC;gBAChCP,MAAM,CAAC,EAAEE,MAAM,cAAc,CAAC;YAChC;YAEA,MAAMM,cAAcH,OAAOC,iBAAiB,CAACG,SAAS,CAAC;gBACrD,MAAMC,QAAQL,OAAOC,iBAAiB,CAACK,QAAQ;gBAC/C,MAAM,EAAEC,OAAO,EAAEC,QAAQ,EAAE,GAAGH,KAAK,CAACR,MAAM;gBAE1C,IAAI,CAACU,WAAWC,UAAU;oBACxBL;oBAEAJ,QAAQS;gBACV;YACF;QACF;IACF,GAAGb;AACL"}
|
package/dist/esm/matchers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/matchers.ts"],"sourcesContent":["/* eslint-disable no-invalid-this */\n\n// Note: Because this file imports from `@jest/globals`, it can only be used in\n// a Jest environment. This is why it's not exported from the index file.\n\nimport { expect } from '@jest/globals';\nimport { NotificationType } from '@metamask/rpc-methods';\nimport { Component } from '@metamask/snaps-ui';\nimport { EnumToUnion } from '@metamask/snaps-utils';\nimport { hasProperty, Json } from '@metamask/utils';\nimport type { MatcherFunction } from 'expect';\nimport {\n diff,\n matcherErrorMessage,\n matcherHint,\n MatcherHintOptions,\n printReceived,\n printWithType,\n RECEIVED_COLOR,\n} from 'jest-matcher-utils';\nimport { is } from 'superstruct';\n\nimport { InterfaceStruct, SnapResponseStruct } from './internals';\nimport { SnapResponse } from './types';\n\n/**\n * Ensure that the actual value is a response from the `request` function.\n *\n * @param actual - The actual value.\n * @param matcherName - The name of the matcher.\n * @param options - The matcher options.\n */\nfunction assertActualIsSnapResponse(\n actual: unknown,\n matcherName: string,\n options?: MatcherHintOptions,\n): asserts actual is SnapResponse {\n if (!is(actual, SnapResponseStruct)) {\n throw new Error(\n matcherErrorMessage(\n matcherHint(matcherName, undefined, undefined, options),\n `${RECEIVED_COLOR(\n 'received',\n )} value must be a response from the \\`request\\` function`,\n printWithType('Received', actual, printReceived),\n ),\n );\n }\n}\n\n/**\n * Ensure that the actual value is a response from the `request` function, and\n * that it has a `ui` property.\n *\n * @param actual - The actual value.\n * @param matcherName - The name of the matcher.\n * @param options - The matcher options.\n */\nfunction assertHasInterface(\n actual: unknown,\n matcherName: string,\n options?: MatcherHintOptions,\n): asserts actual is { content: Component } {\n if (!is(actual, InterfaceStruct) || !actual.content) {\n throw new Error(\n matcherErrorMessage(\n matcherHint(matcherName, undefined, undefined, options),\n `${RECEIVED_COLOR('received')} value must have a \\`content\\` property`,\n printWithType('Received', actual, printReceived),\n ),\n );\n }\n}\n\n/**\n * Check if a JSON-RPC response matches the expected value. This matcher is\n * intended to be used with the `expect` global.\n *\n * @param actual - The actual response.\n * @param expected - The expected response.\n * @returns The status and message.\n */\nexport const toRespondWith: MatcherFunction<[expected: Json]> = function (\n actual,\n expected,\n) {\n assertActualIsSnapResponse(actual, 'toRespondWith');\n\n const { response } = actual;\n if (hasProperty(response, 'error')) {\n const message = () =>\n `${this.utils.matcherHint('.toRespondWith')}\\n\\n` +\n `Expected response: ${this.utils.printExpected(expected)}\\n` +\n `Received error: ${this.utils.printReceived(response.error)}`;\n\n return { message, pass: false };\n }\n\n const pass = this.equals(response.result, expected);\n const message = pass\n ? () =>\n `${this.utils.matcherHint('.not.toRespondWith')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(response.result)}`\n : () =>\n `${this.utils.matcherHint('.toRespondWith')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(response.result)}`;\n\n return { message, pass };\n};\n\nexport const toRespondWithError: MatcherFunction<[expected: Json]> = function (\n actual,\n expected,\n) {\n assertActualIsSnapResponse(actual, 'toRespondWithError');\n\n const { response } = actual;\n if (hasProperty(response, 'result')) {\n const message = () =>\n `${this.utils.matcherHint('.toRespondWithError')}\\n\\n` +\n `Expected error: ${this.utils.printExpected(expected)}\\n` +\n `Received result: ${this.utils.printReceived(response.result)}`;\n\n return { message, pass: false };\n }\n\n const pass = this.equals(response.error, expected);\n const message = pass\n ? () =>\n `${this.utils.matcherHint('.not.toRespondWithError')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(response.error)}`\n : () =>\n `${this.utils.matcherHint('.toRespondWithError')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(response.error)}`;\n\n return { message, pass };\n};\n\n/**\n * Check if the snap sent a notification with the expected message. This matcher\n * is intended to be used with the `expect` global.\n *\n * @param actual - The actual response.\n * @param expected - The expected notification message.\n * @param type - The expected notification type.\n * @returns The status and message.\n */\nexport const toSendNotification: MatcherFunction<\n [expected: string, type?: EnumToUnion<NotificationType> | undefined]\n> = async function (actual, expected, type) {\n assertActualIsSnapResponse(actual, 'toSendNotification');\n\n const { notifications } = actual;\n const pass = notifications.some(\n (notification) =>\n this.equals(notification.message, expected) &&\n (type === undefined || notification.type === type),\n );\n\n const message = pass\n ? () =>\n `${this.utils.matcherHint('.not.toSendNotification')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Expected type: ${this.utils.printExpected(type)}\\n` +\n `Received: ${this.utils.printReceived(notifications)}`\n : () =>\n `${this.utils.matcherHint('.toSendNotification')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Expected type: ${this.utils.printExpected(type)}\\n` +\n `Received: ${this.utils.printReceived(notifications)}`;\n\n return { message, pass };\n};\n\nexport const toRender: MatcherFunction<[expected: Component]> = function (\n actual,\n expected,\n) {\n assertHasInterface(actual, 'toRender');\n\n const { content } = actual;\n const pass = this.equals(content, expected);\n\n const difference = diff(expected, content);\n\n const message = pass\n ? () =>\n `${this.utils.matcherHint('.not.toShowInterface')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(content)}` +\n `${difference ? `\\n\\nDifference:\\n\\n${difference}` : ''}`\n : () =>\n `${this.utils.matcherHint('.toShowInterface')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(content)}` +\n `${difference ? `\\n\\nDifference:\\n\\n${difference}` : ''}`;\n\n return { message, pass };\n};\n\nexpect.extend({\n toRespondWith,\n toRespondWithError,\n toSendNotification,\n toRender,\n});\n"],"names":["expect","hasProperty","diff","matcherErrorMessage","matcherHint","printReceived","printWithType","RECEIVED_COLOR","is","InterfaceStruct","SnapResponseStruct","assertActualIsSnapResponse","actual","matcherName","options","Error","undefined","assertHasInterface","content","toRespondWith","expected","response","message","utils","printExpected","error","pass","equals","result","toRespondWithError","toSendNotification","type","notifications","some","notification","toRender","difference","extend"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/matchers.ts"],"sourcesContent":["/* eslint-disable no-invalid-this */\n\n// Note: Because this file imports from `@jest/globals`, it can only be used in\n// a Jest environment. This is why it's not exported from the index file.\n\nimport { expect } from '@jest/globals';\nimport type { NotificationType } from '@metamask/rpc-methods';\nimport type { Component } from '@metamask/snaps-ui';\nimport type { EnumToUnion } from '@metamask/snaps-utils';\nimport type { Json } from '@metamask/utils';\nimport { hasProperty } from '@metamask/utils';\nimport type { MatcherFunction } from 'expect';\nimport type { MatcherHintOptions } from 'jest-matcher-utils';\nimport {\n diff,\n matcherErrorMessage,\n matcherHint,\n printReceived,\n printWithType,\n RECEIVED_COLOR,\n} from 'jest-matcher-utils';\nimport { is } from 'superstruct';\n\nimport { InterfaceStruct, SnapResponseStruct } from './internals';\nimport type { SnapResponse } from './types';\n\n/**\n * Ensure that the actual value is a response from the `request` function.\n *\n * @param actual - The actual value.\n * @param matcherName - The name of the matcher.\n * @param options - The matcher options.\n */\nfunction assertActualIsSnapResponse(\n actual: unknown,\n matcherName: string,\n options?: MatcherHintOptions,\n): asserts actual is SnapResponse {\n if (!is(actual, SnapResponseStruct)) {\n throw new Error(\n matcherErrorMessage(\n matcherHint(matcherName, undefined, undefined, options),\n `${RECEIVED_COLOR(\n 'received',\n )} value must be a response from the \\`request\\` function`,\n printWithType('Received', actual, printReceived),\n ),\n );\n }\n}\n\n/**\n * Ensure that the actual value is a response from the `request` function, and\n * that it has a `ui` property.\n *\n * @param actual - The actual value.\n * @param matcherName - The name of the matcher.\n * @param options - The matcher options.\n */\nfunction assertHasInterface(\n actual: unknown,\n matcherName: string,\n options?: MatcherHintOptions,\n): asserts actual is { content: Component } {\n if (!is(actual, InterfaceStruct) || !actual.content) {\n throw new Error(\n matcherErrorMessage(\n matcherHint(matcherName, undefined, undefined, options),\n `${RECEIVED_COLOR('received')} value must have a \\`content\\` property`,\n printWithType('Received', actual, printReceived),\n ),\n );\n }\n}\n\n/**\n * Check if a JSON-RPC response matches the expected value. This matcher is\n * intended to be used with the `expect` global.\n *\n * @param actual - The actual response.\n * @param expected - The expected response.\n * @returns The status and message.\n */\nexport const toRespondWith: MatcherFunction<[expected: Json]> = function (\n actual,\n expected,\n) {\n assertActualIsSnapResponse(actual, 'toRespondWith');\n\n const { response } = actual;\n if (hasProperty(response, 'error')) {\n const message = () =>\n `${this.utils.matcherHint('.toRespondWith')}\\n\\n` +\n `Expected response: ${this.utils.printExpected(expected)}\\n` +\n `Received error: ${this.utils.printReceived(response.error)}`;\n\n return { message, pass: false };\n }\n\n const pass = this.equals(response.result, expected);\n const message = pass\n ? () =>\n `${this.utils.matcherHint('.not.toRespondWith')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(response.result)}`\n : () =>\n `${this.utils.matcherHint('.toRespondWith')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(response.result)}`;\n\n return { message, pass };\n};\n\nexport const toRespondWithError: MatcherFunction<[expected: Json]> = function (\n actual,\n expected,\n) {\n assertActualIsSnapResponse(actual, 'toRespondWithError');\n\n const { response } = actual;\n if (hasProperty(response, 'result')) {\n const message = () =>\n `${this.utils.matcherHint('.toRespondWithError')}\\n\\n` +\n `Expected error: ${this.utils.printExpected(expected)}\\n` +\n `Received result: ${this.utils.printReceived(response.result)}`;\n\n return { message, pass: false };\n }\n\n const pass = this.equals(response.error, expected);\n const message = pass\n ? () =>\n `${this.utils.matcherHint('.not.toRespondWithError')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(response.error)}`\n : () =>\n `${this.utils.matcherHint('.toRespondWithError')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(response.error)}`;\n\n return { message, pass };\n};\n\n/**\n * Check if the snap sent a notification with the expected message. This matcher\n * is intended to be used with the `expect` global.\n *\n * @param actual - The actual response.\n * @param expected - The expected notification message.\n * @param type - The expected notification type.\n * @returns The status and message.\n */\nexport const toSendNotification: MatcherFunction<\n [expected: string, type?: EnumToUnion<NotificationType> | undefined]\n> = async function (actual, expected, type) {\n assertActualIsSnapResponse(actual, 'toSendNotification');\n\n const { notifications } = actual;\n const pass = notifications.some(\n (notification) =>\n this.equals(notification.message, expected) &&\n (type === undefined || notification.type === type),\n );\n\n const message = pass\n ? () =>\n `${this.utils.matcherHint('.not.toSendNotification')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Expected type: ${this.utils.printExpected(type)}\\n` +\n `Received: ${this.utils.printReceived(notifications)}`\n : () =>\n `${this.utils.matcherHint('.toSendNotification')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Expected type: ${this.utils.printExpected(type)}\\n` +\n `Received: ${this.utils.printReceived(notifications)}`;\n\n return { message, pass };\n};\n\nexport const toRender: MatcherFunction<[expected: Component]> = function (\n actual,\n expected,\n) {\n assertHasInterface(actual, 'toRender');\n\n const { content } = actual;\n const pass = this.equals(content, expected);\n\n const difference = diff(expected, content);\n\n const message = pass\n ? () =>\n `${this.utils.matcherHint('.not.toShowInterface')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(content)}` +\n `${difference ? `\\n\\nDifference:\\n\\n${difference}` : ''}`\n : () =>\n `${this.utils.matcherHint('.toShowInterface')}\\n\\n` +\n `Expected: ${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(content)}` +\n `${difference ? `\\n\\nDifference:\\n\\n${difference}` : ''}`;\n\n return { message, pass };\n};\n\nexpect.extend({\n toRespondWith,\n toRespondWithError,\n toSendNotification,\n toRender,\n});\n"],"names":["expect","hasProperty","diff","matcherErrorMessage","matcherHint","printReceived","printWithType","RECEIVED_COLOR","is","InterfaceStruct","SnapResponseStruct","assertActualIsSnapResponse","actual","matcherName","options","Error","undefined","assertHasInterface","content","toRespondWith","expected","response","message","utils","printExpected","error","pass","equals","result","toRespondWithError","toSendNotification","type","notifications","some","notification","toRender","difference","extend"],"mappings":"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"}
|
package/dist/esm/options.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/options.ts"],"sourcesContent":["import {\n boolean,\n create,\n defaulted,\n
|
|
1
|
+
{"version":3,"sources":["../../src/options.ts"],"sourcesContent":["import type { Infer } from 'superstruct';\nimport {\n boolean,\n create,\n defaulted,\n number,\n object,\n optional,\n string,\n type,\n} from 'superstruct';\n\nconst SnapsEnvironmentOptionsStruct = type({\n executionEnvironmentUrl: optional(string()),\n simulatorUrl: optional(string()),\n keepAlive: defaulted(boolean(), false),\n\n server: defaulted(\n object({\n enabled: defaulted(boolean(), true),\n port: defaulted(number(), 0),\n root: defaulted(string(), process.cwd()),\n }),\n {},\n ),\n\n browser: defaulted(\n object({\n headless: defaulted(boolean(), true),\n }),\n {},\n ),\n});\n\n/**\n * The options for the environment. These can be specified in the Jest\n * configuration under `testEnvironmentOptions`.\n *\n * @example\n * ```json\n * {\n * \"testEnvironment\": \"@metamask/snaps-jest\",\n * \"testEnvironmentOptions\": {\n * \"executionEnvironmentUrl\": \"http://localhost:8080\",\n * \"server\": {\n * \"port\": 8080,\n * /* ... *\\/\n * }\n * }\n * }\n * ```\n * @property executionEnvironmentUrl - The URL of the execution environment. If\n * this is not provided, the execution environment will be served from the\n * built-in HTTP server.\n * @property simulatorUrl - The URL of the simulator. If this is not provided,\n * the simulator will be served from the built-in HTTP server.\n * @property keepAlive - Whether to keep the browser open after the tests have\n * finished. This is useful for debugging. Defaults to `false`.\n * @property server - The options for the built-in HTTP server.\n * @property server.enabled - Whether to run the built-in HTTP server. Defaults\n * to `true`.\n * @property server.port - The port to use for the built-in HTTP server. If this\n * is not provided, a random available port will be used.\n * @property server.root - The root directory to serve from the built-in HTTP\n * server. Defaults to the current working directory. This is assumed to be the\n * directory containing the snap manifest and `dist` files. If this is a\n * relative path, it will be resolved relative to the current working directory.\n * @property browser - The options for the browser.\n * @property browser.headless - Whether to run the browser in headless mode.\n * Defaults to `true`.\n */\nexport type SnapsEnvironmentOptions = Infer<\n typeof SnapsEnvironmentOptionsStruct\n>;\n\n/**\n * Get the environment options. This validates the options, and returns the\n * default options if none are provided.\n *\n * @param testEnvironmentOptions - The test environment options as defined in\n * the Jest configuration.\n * @returns The environment options.\n */\nexport function getOptions(testEnvironmentOptions: Record<string, unknown>) {\n return create(testEnvironmentOptions, SnapsEnvironmentOptionsStruct);\n}\n"],"names":["boolean","create","defaulted","number","object","optional","string","type","SnapsEnvironmentOptionsStruct","executionEnvironmentUrl","simulatorUrl","keepAlive","server","enabled","port","root","process","cwd","browser","headless","getOptions","testEnvironmentOptions"],"mappings":"AACA,SACEA,OAAO,EACPC,MAAM,EACNC,SAAS,EACTC,MAAM,EACNC,MAAM,EACNC,QAAQ,EACRC,MAAM,EACNC,IAAI,QACC,cAAc;AAErB,MAAMC,gCAAgCD,KAAK;IACzCE,yBAAyBJ,SAASC;IAClCI,cAAcL,SAASC;IACvBK,WAAWT,UAAUF,WAAW;IAEhCY,QAAQV,UACNE,OAAO;QACLS,SAASX,UAAUF,WAAW;QAC9Bc,MAAMZ,UAAUC,UAAU;QAC1BY,MAAMb,UAAUI,UAAUU,QAAQC,GAAG;IACvC,IACA,CAAC;IAGHC,SAAShB,UACPE,OAAO;QACLe,UAAUjB,UAAUF,WAAW;IACjC,IACA,CAAC;AAEL;AA2CA;;;;;;;CAOC,GACD,OAAO,SAASoB,WAAWC,sBAA+C;IACxE,OAAOpB,OAAOoB,wBAAwBb;AACxC"}
|
package/dist/esm/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/types.ts"],"sourcesContent":["import { NotificationType } from '@metamask/rpc-methods';\nimport { Component } from '@metamask/snaps-ui';\nimport { EnumToUnion } from '@metamask/snaps-utils';\nimport { JsonRpcId, JsonRpcParams } from '@metamask/utils';\nimport { Infer } from 'superstruct';\n\nimport {\n Mock,\n MockJsonRpcOptions,\n MockOptions,\n SnapOptionsStruct,\n SnapResponseStruct,\n TransactionOptionsStruct,\n} from './internals';\n\n/* eslint-disable @typescript-eslint/consistent-type-definitions */\ndeclare module 'expect' {\n interface AsymmetricMatchers {\n toRespondWith(response: unknown): void;\n toRespondWithError(error: unknown): void;\n toSendNotification(\n message: string,\n type?: EnumToUnion<NotificationType>,\n ): void;\n toRender(component: Component): void;\n }\n\n // Ideally we would use `Matchers<Result>` instead of `Matchers<R>`, but\n // TypeScript doesn't allow this:\n // TS2428: All declarations of 'Matchers' must have identical type parameters.\n interface Matchers<R> {\n toRespondWith(response: unknown): R;\n toRespondWithError(error: unknown): R;\n toSendNotification(\n message: string,\n type?: EnumToUnion<NotificationType>,\n ): R;\n toRender(component: Component): R;\n }\n}\n/* eslint-enable @typescript-eslint/consistent-type-definitions */\n\n/**\n * Deeply partialize a type.\n *\n * @template Type - The type to partialize.\n * @returns The deeply partialized type.\n * @example\n * ```ts\n * type Foo = {\n * bar: {\n * baz: string;\n * };\n * qux: number;\n * };\n *\n * type PartialFoo = DeepPartial<Foo>;\n * // { bar?: { baz?: string; }; qux?: number; }\n * ```\n */\nexport type DeepPartial<Type> = {\n [Key in keyof Type]?: Type[Key] extends Record<string, unknown>\n ? DeepPartial<Type[Key]>\n : Type[Key];\n};\n\nexport type RequestOptions = {\n /**\n * The JSON-RPC request ID.\n */\n id?: JsonRpcId;\n\n /**\n * The JSON-RPC method.\n */\n method: string;\n\n /**\n * The JSON-RPC params.\n */\n params?: JsonRpcParams;\n\n /**\n * The origin to send the request from.\n */\n origin?: string;\n};\n\n/**\n * The `runCronjob` options. This is the same as {@link RequestOptions}, except\n * that it does not have an `origin` property.\n */\nexport type CronjobOptions = Omit<RequestOptions, 'origin'>;\n\n/**\n * The options to use for transaction requests.\n *\n * @property chainId - The CAIP-2 chain ID to send the transaction on. Defaults\n * to `eip155:1`.\n * @property origin - The origin to send the transaction from. Defaults to\n * `metamask.io`.\n * @property from - The address to send the transaction from. Defaults to a\n * randomly generated address.\n * @property to - The address to send the transaction to. Defaults to a randomly\n * generated address.\n * @property value - The value to send with the transaction. Defaults to `0`.\n * @property data - The data to send with the transaction. Defaults to `0x`.\n * @property gasLimit - The gas limit to use for the transaction. Defaults to\n * `21_000`.\n * @property maxFeePerGas - The maximum fee per gas to use for the transaction.\n * Defaults to `1`.\n * @property maxPriorityFeePerGas - The maximum priority fee per gas to use for\n * the transaction. Defaults to `1`.\n * @property nonce - The nonce to use for the transaction. Defaults to `0`.\n */\nexport type TransactionOptions = Infer<typeof TransactionOptionsStruct>;\n\n/**\n * The options to use for requests to the snap.\n *\n * @property timeout - The timeout in milliseconds to use. Defaults to `1000`.\n */\nexport type SnapOptions = Infer<typeof SnapOptionsStruct>;\n\n/**\n * A `snap_dialog` alert interface.\n */\nexport type SnapAlertInterface = {\n /**\n * The type of the interface. This is always `alert`.\n */\n type: 'alert';\n\n /**\n * The content to show in the alert.\n */\n content: Component;\n\n /**\n * Close the alert.\n */\n ok(): Promise<void>;\n};\n\n/**\n * A `snap_dialog` confirmation interface.\n */\nexport type SnapConfirmationInterface = {\n /**\n * The type of the interface. This is always `confirmation`.\n */\n type: 'confirmation';\n\n /**\n * The content to show in the confirmation.\n */\n content: Component;\n\n /**\n * Close the confirmation.\n */\n ok(): Promise<void>;\n\n /**\n * Cancel the confirmation.\n */\n cancel(): Promise<void>;\n};\n\n/**\n * A `snap_dialog` prompt interface.\n */\nexport type SnapPromptInterface = {\n /**\n * The type of the interface. This is always `prompt`.\n */\n type: 'prompt';\n\n /**\n * The content to show in the prompt.\n */\n content: Component;\n\n /**\n * Close the prompt.\n *\n * @param value - The value to close the prompt with.\n */\n ok(value?: string): Promise<void>;\n\n /**\n * Cancel the prompt.\n */\n cancel(): Promise<void>;\n};\n\nexport type SnapInterface =\n | SnapAlertInterface\n | SnapConfirmationInterface\n | SnapPromptInterface;\n\nexport type SnapRequestObject = {\n /**\n * Get a user interface object from a snap. This will throw an error if the\n * snap does not show a user interface within the timeout.\n *\n * @param options - The options to use.\n * @param options.timeout - The timeout in milliseconds to use. Defaults to\n * `1000`.\n * @returns The user interface object.\n */\n getInterface(options?: SnapOptions): Promise<SnapInterface>;\n};\n\n/**\n * A pending request object. This is a promise with extra\n * {@link SnapRequestObject} fields.\n */\nexport type SnapRequest = Promise<SnapResponse> & SnapRequestObject;\n\n/**\n * This is the main entry point to interact with the snap. It is returned by\n * {@link installSnap}, and has methods to send requests to the snap.\n *\n * @example\n * ```ts\n * import { installSnap } from '@metamask/snaps-jest';\n *\n * const snap = await installSnap();\n * const response = await snap.request({ method: 'hello' });\n *\n * expect(response).toRespondWith('Hello, world!');\n * ```\n */\nexport type Snap = {\n /**\n * Send a JSON-RPC request to the snap.\n *\n * @param request - The request. This is similar to a JSON-RPC request, but\n * has an extra `origin` field.\n * @returns The response promise, with extra {@link SnapRequestObject} fields.\n */\n request(request: RequestOptions): SnapRequest;\n\n /**\n * Send a transaction to the snap.\n *\n * @param transaction - The transaction. This is similar to an Ethereum\n * transaction object, but has an extra `origin` field. Any missing fields\n * will be filled in with default values.\n * @returns The response.\n */\n sendTransaction(\n transaction?: Partial<TransactionOptions>,\n ): Promise<SnapResponse>;\n\n /**\n * Run a cronjob in the snap. This is similar to {@link request}, but the\n * request will be sent to the `onCronjob` method of the snap.\n *\n * @param cronjob - The cronjob request. This is similar to a JSON-RPC\n * request, and is normally specified in the snap manifest, under the\n * `endowment:cronjob` permission.\n * @returns The response promise, with extra {@link SnapRequestObject} fields.\n */\n runCronjob(cronjob: CronjobOptions): SnapRequest;\n\n /**\n * Close the page running the snap. This is mainly useful for cleaning up\n * the test environment, and calling it is not strictly necessary.\n *\n * @returns A promise that resolves when the page is closed.\n */\n // TODO: Find a way to do this automatically.\n close(): Promise<void>;\n\n /**\n * Enable network mocking for the snap.\n *\n * @param options - The options for the network mocking.\n * @returns A {@link Mock} object, with an `unmock` function.\n */\n mock(options: DeepPartial<MockOptions>): Promise<Mock>;\n\n /**\n * Enable JSON-RPC provider mocking for the snap. This will mock any requests\n * sent through the `ethereum` global, with the specified `method`.\n *\n * @param options - The options for the JSON-RPC mocking.\n * @param options.method - The JSON-RPC method to mock, e.g.,\n * `eth_blockNumber`.\n * @param options.result - The JSON value to return.\n * @returns A {@link Mock} object, with an `unmock` function.\n */\n mockJsonRpc(options: MockJsonRpcOptions): Promise<Mock>;\n};\n\nexport type SnapResponse = Infer<typeof SnapResponseStruct>;\n\nexport { NotificationType } from '@metamask/rpc-methods';\n"],"names":["NotificationType"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/types.ts"],"sourcesContent":["import type { NotificationType } from '@metamask/rpc-methods';\nimport type { Component } from '@metamask/snaps-ui';\nimport type { EnumToUnion } from '@metamask/snaps-utils';\nimport type { JsonRpcId, JsonRpcParams } from '@metamask/utils';\nimport type { Infer } from 'superstruct';\n\nimport type {\n Mock,\n MockJsonRpcOptions,\n MockOptions,\n SnapOptionsStruct,\n SnapResponseStruct,\n TransactionOptionsStruct,\n} from './internals';\n\n/* eslint-disable @typescript-eslint/consistent-type-definitions */\ndeclare module 'expect' {\n interface AsymmetricMatchers {\n toRespondWith(response: unknown): void;\n toRespondWithError(error: unknown): void;\n toSendNotification(\n message: string,\n type?: EnumToUnion<NotificationType>,\n ): void;\n toRender(component: Component): void;\n }\n\n // Ideally we would use `Matchers<Result>` instead of `Matchers<R>`, but\n // TypeScript doesn't allow this:\n // TS2428: All declarations of 'Matchers' must have identical type parameters.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n interface Matchers<R> {\n toRespondWith(response: unknown): R;\n toRespondWithError(error: unknown): R;\n toSendNotification(\n message: string,\n type?: EnumToUnion<NotificationType>,\n ): R;\n toRender(component: Component): R;\n }\n}\n/* eslint-enable @typescript-eslint/consistent-type-definitions */\n\n/**\n * Deeply partialize a type.\n *\n * @template Type - The type to partialize.\n * @returns The deeply partialized type.\n * @example\n * ```ts\n * type Foo = {\n * bar: {\n * baz: string;\n * };\n * qux: number;\n * };\n *\n * type PartialFoo = DeepPartial<Foo>;\n * // { bar?: { baz?: string; }; qux?: number; }\n * ```\n */\nexport type DeepPartial<Type> = {\n [Key in keyof Type]?: Type[Key] extends Record<string, unknown>\n ? DeepPartial<Type[Key]>\n : Type[Key];\n};\n\nexport type RequestOptions = {\n /**\n * The JSON-RPC request ID.\n */\n id?: JsonRpcId;\n\n /**\n * The JSON-RPC method.\n */\n method: string;\n\n /**\n * The JSON-RPC params.\n */\n params?: JsonRpcParams;\n\n /**\n * The origin to send the request from.\n */\n origin?: string;\n};\n\n/**\n * The `runCronjob` options. This is the same as {@link RequestOptions}, except\n * that it does not have an `origin` property.\n */\nexport type CronjobOptions = Omit<RequestOptions, 'origin'>;\n\n/**\n * The options to use for transaction requests.\n *\n * @property chainId - The CAIP-2 chain ID to send the transaction on. Defaults\n * to `eip155:1`.\n * @property origin - The origin to send the transaction from. Defaults to\n * `metamask.io`.\n * @property from - The address to send the transaction from. Defaults to a\n * randomly generated address.\n * @property to - The address to send the transaction to. Defaults to a randomly\n * generated address.\n * @property value - The value to send with the transaction. Defaults to `0`.\n * @property data - The data to send with the transaction. Defaults to `0x`.\n * @property gasLimit - The gas limit to use for the transaction. Defaults to\n * `21_000`.\n * @property maxFeePerGas - The maximum fee per gas to use for the transaction.\n * Defaults to `1`.\n * @property maxPriorityFeePerGas - The maximum priority fee per gas to use for\n * the transaction. Defaults to `1`.\n * @property nonce - The nonce to use for the transaction. Defaults to `0`.\n */\nexport type TransactionOptions = Infer<typeof TransactionOptionsStruct>;\n\n/**\n * The options to use for requests to the snap.\n *\n * @property timeout - The timeout in milliseconds to use. Defaults to `1000`.\n */\nexport type SnapOptions = Infer<typeof SnapOptionsStruct>;\n\n/**\n * A `snap_dialog` alert interface.\n */\nexport type SnapAlertInterface = {\n /**\n * The type of the interface. This is always `alert`.\n */\n type: 'alert';\n\n /**\n * The content to show in the alert.\n */\n content: Component;\n\n /**\n * Close the alert.\n */\n ok(): Promise<void>;\n};\n\n/**\n * A `snap_dialog` confirmation interface.\n */\nexport type SnapConfirmationInterface = {\n /**\n * The type of the interface. This is always `confirmation`.\n */\n type: 'confirmation';\n\n /**\n * The content to show in the confirmation.\n */\n content: Component;\n\n /**\n * Close the confirmation.\n */\n ok(): Promise<void>;\n\n /**\n * Cancel the confirmation.\n */\n cancel(): Promise<void>;\n};\n\n/**\n * A `snap_dialog` prompt interface.\n */\nexport type SnapPromptInterface = {\n /**\n * The type of the interface. This is always `prompt`.\n */\n type: 'prompt';\n\n /**\n * The content to show in the prompt.\n */\n content: Component;\n\n /**\n * Close the prompt.\n *\n * @param value - The value to close the prompt with.\n */\n ok(value?: string): Promise<void>;\n\n /**\n * Cancel the prompt.\n */\n cancel(): Promise<void>;\n};\n\nexport type SnapInterface =\n | SnapAlertInterface\n | SnapConfirmationInterface\n | SnapPromptInterface;\n\nexport type SnapRequestObject = {\n /**\n * Get a user interface object from a snap. This will throw an error if the\n * snap does not show a user interface within the timeout.\n *\n * @param options - The options to use.\n * @param options.timeout - The timeout in milliseconds to use. Defaults to\n * `1000`.\n * @returns The user interface object.\n */\n getInterface(options?: SnapOptions): Promise<SnapInterface>;\n};\n\n/**\n * A pending request object. This is a promise with extra\n * {@link SnapRequestObject} fields.\n */\nexport type SnapRequest = Promise<SnapResponse> & SnapRequestObject;\n\n/**\n * This is the main entry point to interact with the snap. It is returned by\n * {@link installSnap}, and has methods to send requests to the snap.\n *\n * @example\n * ```ts\n * import { installSnap } from '@metamask/snaps-jest';\n *\n * const snap = await installSnap();\n * const response = await snap.request({ method: 'hello' });\n *\n * expect(response).toRespondWith('Hello, world!');\n * ```\n */\nexport type Snap = {\n /**\n * Send a JSON-RPC request to the snap.\n *\n * @param request - The request. This is similar to a JSON-RPC request, but\n * has an extra `origin` field.\n * @returns The response promise, with extra {@link SnapRequestObject} fields.\n */\n request(request: RequestOptions): SnapRequest;\n\n /**\n * Send a transaction to the snap.\n *\n * @param transaction - The transaction. This is similar to an Ethereum\n * transaction object, but has an extra `origin` field. Any missing fields\n * will be filled in with default values.\n * @returns The response.\n */\n sendTransaction(\n transaction?: Partial<TransactionOptions>,\n ): Promise<SnapResponse>;\n\n /**\n * Run a cronjob in the snap. This is similar to {@link request}, but the\n * request will be sent to the `onCronjob` method of the snap.\n *\n * @param cronjob - The cronjob request. This is similar to a JSON-RPC\n * request, and is normally specified in the snap manifest, under the\n * `endowment:cronjob` permission.\n * @returns The response promise, with extra {@link SnapRequestObject} fields.\n */\n runCronjob(cronjob: CronjobOptions): SnapRequest;\n\n /**\n * Close the page running the snap. This is mainly useful for cleaning up\n * the test environment, and calling it is not strictly necessary.\n *\n * @returns A promise that resolves when the page is closed.\n */\n // TODO: Find a way to do this automatically.\n close(): Promise<void>;\n\n /**\n * Enable network mocking for the snap.\n *\n * @param options - The options for the network mocking.\n * @returns A {@link Mock} object, with an `unmock` function.\n */\n mock(options: DeepPartial<MockOptions>): Promise<Mock>;\n\n /**\n * Enable JSON-RPC provider mocking for the snap. This will mock any requests\n * sent through the `ethereum` global, with the specified `method`.\n *\n * @param options - The options for the JSON-RPC mocking.\n * @param options.method - The JSON-RPC method to mock, e.g.,\n * `eth_blockNumber`.\n * @param options.result - The JSON value to return.\n * @returns A {@link Mock} object, with an `unmock` function.\n */\n mockJsonRpc(options: MockJsonRpcOptions): Promise<Mock>;\n};\n\nexport type SnapResponse = Infer<typeof SnapResponseStruct>;\n\nexport { NotificationType } from '@metamask/rpc-methods';\n"],"names":["NotificationType"],"mappings":"AA4SA,SAASA,gBAAgB,QAAQ,wBAAwB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EnvironmentContext, JestEnvironmentConfig } from '@jest/environment';
|
|
1
|
+
import type { EnvironmentContext, JestEnvironmentConfig } from '@jest/environment';
|
|
2
2
|
import NodeEnvironment from 'jest-environment-node';
|
|
3
3
|
declare global {
|
|
4
4
|
const browser: WebdriverIO.Browser;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Page } from 'puppeteer';
|
|
2
|
-
import { SnapInterface, SnapOptions } from '../types';
|
|
1
|
+
import type { Page } from 'puppeteer';
|
|
2
|
+
import type { SnapInterface, SnapOptions } from '../types';
|
|
3
3
|
/**
|
|
4
4
|
* Get the current snap user interface (i.e., dialog). This will throw an error
|
|
5
5
|
* if the snap does not show a user interface within the timeout.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Page, HTTPRequest } from 'puppeteer';
|
|
2
|
-
import { Infer, Struct } from 'superstruct';
|
|
3
|
-
import { DeepPartial } from '../types';
|
|
1
|
+
import type { Page, HTTPRequest } from 'puppeteer';
|
|
2
|
+
import type { Infer, Struct } from 'superstruct';
|
|
3
|
+
import type { DeepPartial } from '../types';
|
|
4
4
|
export declare type Unmock = () => Promise<void>;
|
|
5
5
|
export declare type Mock = {
|
|
6
6
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HandlerType } from '@metamask/snaps-utils';
|
|
2
|
-
import { Page } from 'puppeteer';
|
|
3
|
-
import { CronjobOptions, RequestOptions, SnapRequest, TransactionOptions } from '../types';
|
|
2
|
+
import type { Page } from 'puppeteer';
|
|
3
|
+
import type { CronjobOptions, RequestOptions, SnapRequest, TransactionOptions } from '../types';
|
|
4
4
|
/**
|
|
5
5
|
* Send a request to the snap.
|
|
6
6
|
*
|
|
@@ -46,6 +46,7 @@ export declare function sendTransaction(page: Page, options: Partial<Transaction
|
|
|
46
46
|
} | {
|
|
47
47
|
value: string;
|
|
48
48
|
type: import("@metamask/snaps-ui").NodeType.Text;
|
|
49
|
+
markdown?: boolean | undefined;
|
|
49
50
|
};
|
|
50
51
|
}>;
|
|
51
52
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { Server } from 'http';
|
|
3
|
-
import { SnapsEnvironmentOptions } from '../options';
|
|
2
|
+
import type { Server } from 'http';
|
|
3
|
+
import type { SnapsEnvironmentOptions } from '../options';
|
|
4
4
|
export declare type ServerOptions = Required<Required<SnapsEnvironmentOptions>['server']>;
|
|
5
5
|
/**
|
|
6
6
|
* Start an HTTP server on `localhost` with a random port. This is used to serve
|
|
@@ -84,6 +84,7 @@ export declare const InterfaceStruct: import("superstruct").Struct<{
|
|
|
84
84
|
} | {
|
|
85
85
|
value: string;
|
|
86
86
|
type: import("@metamask/snaps-ui").NodeType.Text;
|
|
87
|
+
markdown?: boolean | undefined;
|
|
87
88
|
} | undefined;
|
|
88
89
|
}, {
|
|
89
90
|
content: import("superstruct").Struct<import("@metamask/snaps-ui").Panel | {
|
|
@@ -99,6 +100,7 @@ export declare const InterfaceStruct: import("superstruct").Struct<{
|
|
|
99
100
|
} | {
|
|
100
101
|
value: string;
|
|
101
102
|
type: import("@metamask/snaps-ui").NodeType.Text;
|
|
103
|
+
markdown?: boolean | undefined;
|
|
102
104
|
} | undefined, null>;
|
|
103
105
|
}>;
|
|
104
106
|
export declare const SnapResponseStruct: import("superstruct").Struct<{
|
|
@@ -126,6 +128,7 @@ export declare const SnapResponseStruct: import("superstruct").Struct<{
|
|
|
126
128
|
} | {
|
|
127
129
|
value: string;
|
|
128
130
|
type: import("@metamask/snaps-ui").NodeType.Text;
|
|
131
|
+
markdown?: boolean | undefined;
|
|
129
132
|
} | undefined;
|
|
130
133
|
}, {
|
|
131
134
|
id: import("superstruct").Struct<string, null>;
|
|
@@ -160,5 +163,6 @@ export declare const SnapResponseStruct: import("superstruct").Struct<{
|
|
|
160
163
|
} | {
|
|
161
164
|
value: string;
|
|
162
165
|
type: import("@metamask/snaps-ui").NodeType.Text;
|
|
166
|
+
markdown?: boolean | undefined;
|
|
163
167
|
} | undefined, null>;
|
|
164
168
|
}>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { NotificationType } from '@metamask/rpc-methods';
|
|
2
|
-
import { ApplicationState, Dispatch } from '@metamask/snaps-simulator';
|
|
3
|
-
import { EnumToUnion } from '@metamask/snaps-utils';
|
|
1
|
+
import type { NotificationType } from '@metamask/rpc-methods';
|
|
2
|
+
import type { ApplicationState, Dispatch } from '@metamask/snaps-simulator';
|
|
3
|
+
import type { EnumToUnion } from '@metamask/snaps-utils';
|
|
4
4
|
declare global {
|
|
5
5
|
interface Window {
|
|
6
6
|
__SIMULATOR_API__: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { HandlerType } from '@metamask/snaps-utils';
|
|
2
|
-
import { Page } from 'puppeteer';
|
|
1
|
+
import type { HandlerType } from '@metamask/snaps-utils';
|
|
2
|
+
import type { Page } from 'puppeteer';
|
|
3
3
|
export declare type WaitForOptions = {
|
|
4
4
|
/**
|
|
5
5
|
* The timeout in milliseconds.
|
package/dist/types/matchers.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { NotificationType } from '@metamask/rpc-methods';
|
|
2
|
-
import { Component } from '@metamask/snaps-ui';
|
|
3
|
-
import { EnumToUnion } from '@metamask/snaps-utils';
|
|
4
|
-
import { Json } from '@metamask/utils';
|
|
1
|
+
import type { NotificationType } from '@metamask/rpc-methods';
|
|
2
|
+
import type { Component } from '@metamask/snaps-ui';
|
|
3
|
+
import type { EnumToUnion } from '@metamask/snaps-utils';
|
|
4
|
+
import type { Json } from '@metamask/utils';
|
|
5
5
|
import type { MatcherFunction } from 'expect';
|
|
6
6
|
/**
|
|
7
7
|
* Check if a JSON-RPC response matches the expected value. This matcher is
|
package/dist/types/options.d.ts
CHANGED
package/dist/types/types.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { NotificationType } from '@metamask/rpc-methods';
|
|
2
|
-
import { Component } from '@metamask/snaps-ui';
|
|
3
|
-
import { EnumToUnion } from '@metamask/snaps-utils';
|
|
4
|
-
import { JsonRpcId, JsonRpcParams } from '@metamask/utils';
|
|
5
|
-
import { Infer } from 'superstruct';
|
|
6
|
-
import { Mock, MockJsonRpcOptions, MockOptions, SnapOptionsStruct, SnapResponseStruct, TransactionOptionsStruct } from './internals';
|
|
1
|
+
import type { NotificationType } from '@metamask/rpc-methods';
|
|
2
|
+
import type { Component } from '@metamask/snaps-ui';
|
|
3
|
+
import type { EnumToUnion } from '@metamask/snaps-utils';
|
|
4
|
+
import type { JsonRpcId, JsonRpcParams } from '@metamask/utils';
|
|
5
|
+
import type { Infer } from 'superstruct';
|
|
6
|
+
import type { Mock, MockJsonRpcOptions, MockOptions, SnapOptionsStruct, SnapResponseStruct, TransactionOptionsStruct } from './internals';
|
|
7
7
|
declare module 'expect' {
|
|
8
8
|
interface AsymmetricMatchers {
|
|
9
9
|
toRespondWith(response: unknown): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask/snaps-jest",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.0-flask.1",
|
|
4
4
|
"description": "A Jest preset for end-to-end testing MetaMask Snaps, including a Jest environment, and a set of Jest matchers.",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
"@jest/expect": "^29.5.0",
|
|
38
38
|
"@jest/globals": "^29.5.0",
|
|
39
39
|
"@jest/types": "^29.5.0",
|
|
40
|
-
"@metamask/rpc-methods": "^0.
|
|
41
|
-
"@metamask/snaps-execution-environments": "^0.
|
|
42
|
-
"@metamask/snaps-simulator": "^0.
|
|
43
|
-
"@metamask/snaps-ui": "^0.
|
|
44
|
-
"@metamask/snaps-utils": "^0.
|
|
40
|
+
"@metamask/rpc-methods": "^0.37.0-flask.1",
|
|
41
|
+
"@metamask/snaps-execution-environments": "^0.37.0-flask.1",
|
|
42
|
+
"@metamask/snaps-simulator": "^0.37.0-flask.1",
|
|
43
|
+
"@metamask/snaps-ui": "^0.37.0-flask.1",
|
|
44
|
+
"@metamask/snaps-utils": "^0.37.0-flask.1",
|
|
45
45
|
"@metamask/utils": "^6.0.1",
|
|
46
46
|
"express": "^4.18.2",
|
|
47
47
|
"jest-environment-node": "^29.5.0",
|
|
@@ -54,10 +54,10 @@
|
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@lavamoat/allow-scripts": "^2.3.1",
|
|
56
56
|
"@metamask/auto-changelog": "^3.1.0",
|
|
57
|
-
"@metamask/eslint-config": "^
|
|
58
|
-
"@metamask/eslint-config-jest": "^
|
|
59
|
-
"@metamask/eslint-config-nodejs": "^
|
|
60
|
-
"@metamask/eslint-config-typescript": "^
|
|
57
|
+
"@metamask/eslint-config": "^12.1.0",
|
|
58
|
+
"@metamask/eslint-config-jest": "^12.1.0",
|
|
59
|
+
"@metamask/eslint-config-nodejs": "^12.1.0",
|
|
60
|
+
"@metamask/eslint-config-typescript": "^12.1.0",
|
|
61
61
|
"@swc/cli": "^0.1.62",
|
|
62
62
|
"@swc/core": "^1.3.66",
|
|
63
63
|
"@swc/jest": "^0.2.26",
|
|
@@ -71,8 +71,9 @@
|
|
|
71
71
|
"eslint-plugin-import": "^2.26.0",
|
|
72
72
|
"eslint-plugin-jest": "^27.1.5",
|
|
73
73
|
"eslint-plugin-jsdoc": "^39.6.2",
|
|
74
|
-
"eslint-plugin-
|
|
74
|
+
"eslint-plugin-n": "^15.7.0",
|
|
75
75
|
"eslint-plugin-prettier": "^4.2.1",
|
|
76
|
+
"eslint-plugin-promise": "^6.1.1",
|
|
76
77
|
"jest": "^29.0.2",
|
|
77
78
|
"jest-it-up": "^2.0.0",
|
|
78
79
|
"prettier": "^2.7.1",
|