@metamask/snaps-simulation 1.0.0 → 1.1.0

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 CHANGED
@@ -1,4 +1,5 @@
1
1
  # Changelog
2
+
2
3
  All notable changes to this project will be documented in this file.
3
4
 
4
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
@@ -6,9 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
7
 
7
8
  ## [Unreleased]
8
9
 
10
+ ## [1.1.0]
11
+
12
+ ### Changed
13
+
14
+ - Move helper functions to simulation package ([#2769](https://github.com/MetaMask/snaps/pull/2769))
15
+
16
+ ## [1.0.1]
17
+
18
+ ### Fixed
19
+
20
+ - Fix invalid `exports` field ([#2740](https://github.com/MetaMask/snaps/pull/2740))
21
+
9
22
  ## [1.0.0]
23
+
10
24
  ### Added
25
+
11
26
  - Initial release of `@metamask/snaps-simulation` package ([#2727](https://github.com/MetaMask/snaps/pull/2727))
12
27
 
13
- [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-simulation@1.0.0...HEAD
28
+ [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-simulation@1.1.0...HEAD
29
+ [1.1.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-simulation@1.0.1...@metamask/snaps-simulation@1.1.0
30
+ [1.0.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-simulation@1.0.0...@metamask/snaps-simulation@1.0.1
14
31
  [1.0.0]: https://github.com/MetaMask/snaps/releases/tag/@metamask/snaps-simulation@1.0.0
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getHelpers = void 0;
4
+ const snaps_utils_1 = require("@metamask/snaps-utils");
5
+ const superstruct_1 = require("@metamask/superstruct");
6
+ const utils_1 = require("@metamask/utils");
7
+ const logger_1 = require("./logger.cjs");
8
+ const request_1 = require("./request.cjs");
9
+ const store_1 = require("./store/index.cjs");
10
+ const structs_1 = require("./structs.cjs");
11
+ const log = (0, utils_1.createModuleLogger)(logger_1.rootLogger, 'helpers');
12
+ /**
13
+ * Get the helper functions for the Snap.
14
+ *
15
+ * @param snap - The installed Snap.
16
+ * @param snap.snapId - The ID of the Snap.
17
+ * @param snap.store - The Redux store.
18
+ * @param snap.executionService - The execution service.
19
+ * @param snap.runSaga - The `runSaga` function.
20
+ * @param snap.controllerMessenger - The controller messenger.
21
+ * @param snap.options - The simulation options.
22
+ * @returns The Snap helpers.
23
+ */
24
+ function getHelpers({ snapId, store, executionService, runSaga, controllerMessenger, options, }) {
25
+ const onTransaction = async (request) => {
26
+ log('Sending transaction %o.', request);
27
+ const { origin: transactionOrigin, chainId, ...transaction } = (0, superstruct_1.create)(request, structs_1.TransactionOptionsStruct);
28
+ const response = await (0, request_1.handleRequest)({
29
+ snapId,
30
+ store,
31
+ executionService,
32
+ runSaga,
33
+ controllerMessenger,
34
+ handler: snaps_utils_1.HandlerType.OnTransaction,
35
+ request: {
36
+ method: '',
37
+ params: {
38
+ chainId,
39
+ transaction,
40
+ transactionOrigin,
41
+ },
42
+ },
43
+ });
44
+ (0, structs_1.assertIsResponseWithInterface)(response);
45
+ return response;
46
+ };
47
+ const onCronjob = (request) => {
48
+ log('Running cronjob %o.', options);
49
+ return (0, request_1.handleRequest)({
50
+ snapId,
51
+ store,
52
+ executionService,
53
+ controllerMessenger,
54
+ runSaga,
55
+ handler: snaps_utils_1.HandlerType.OnCronjob,
56
+ request,
57
+ });
58
+ };
59
+ return {
60
+ request: (request) => {
61
+ log('Sending request %o.', request);
62
+ return (0, request_1.handleRequest)({
63
+ snapId,
64
+ store,
65
+ executionService,
66
+ controllerMessenger,
67
+ runSaga,
68
+ handler: snaps_utils_1.HandlerType.OnRpcRequest,
69
+ request,
70
+ });
71
+ },
72
+ onTransaction,
73
+ sendTransaction: onTransaction,
74
+ onSignature: async (request) => {
75
+ log('Requesting signature %o.', request);
76
+ const { origin: signatureOrigin, ...signature } = (0, superstruct_1.create)(request, structs_1.SignatureOptionsStruct);
77
+ const response = await (0, request_1.handleRequest)({
78
+ snapId,
79
+ store,
80
+ executionService,
81
+ controllerMessenger,
82
+ runSaga,
83
+ handler: snaps_utils_1.HandlerType.OnSignature,
84
+ request: {
85
+ method: '',
86
+ params: {
87
+ signature,
88
+ signatureOrigin,
89
+ },
90
+ },
91
+ });
92
+ (0, structs_1.assertIsResponseWithInterface)(response);
93
+ return response;
94
+ },
95
+ onCronjob,
96
+ runCronjob: onCronjob,
97
+ onHomePage: async () => {
98
+ log('Rendering home page.');
99
+ const response = await (0, request_1.handleRequest)({
100
+ snapId,
101
+ store,
102
+ executionService,
103
+ controllerMessenger,
104
+ runSaga,
105
+ handler: snaps_utils_1.HandlerType.OnHomePage,
106
+ request: {
107
+ method: '',
108
+ },
109
+ });
110
+ (0, structs_1.assertIsResponseWithInterface)(response);
111
+ return response;
112
+ },
113
+ mockJsonRpc(mock) {
114
+ log('Mocking JSON-RPC request %o.', mock);
115
+ const { method, result } = (0, superstruct_1.create)(mock, structs_1.JsonRpcMockOptionsStruct);
116
+ store.dispatch((0, store_1.addJsonRpcMock)({ method, result }));
117
+ return {
118
+ unmock() {
119
+ log('Unmocking JSON-RPC request %o.', mock);
120
+ store.dispatch((0, store_1.removeJsonRpcMock)(method));
121
+ },
122
+ };
123
+ },
124
+ close: async () => {
125
+ log('Closing execution service.');
126
+ await executionService.terminateAllSnaps();
127
+ },
128
+ };
129
+ }
130
+ exports.getHelpers = getHelpers;
131
+ //# sourceMappingURL=helpers.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.cjs","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import { HandlerType } from '@metamask/snaps-utils';\nimport { create } from '@metamask/superstruct';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { rootLogger } from './logger';\nimport type { SimulationOptions } from './options';\nimport { handleRequest } from './request';\nimport type { InstalledSnap } from './simulation';\nimport { addJsonRpcMock, removeJsonRpcMock } from './store';\nimport {\n assertIsResponseWithInterface,\n JsonRpcMockOptionsStruct,\n SignatureOptionsStruct,\n TransactionOptionsStruct,\n} from './structs';\nimport type {\n CronjobOptions,\n JsonRpcMockOptions,\n RequestOptions,\n SignatureOptions,\n SnapRequest,\n SnapResponseWithInterface,\n TransactionOptions,\n} from './types';\n\nconst log = createModuleLogger(rootLogger, 'helpers');\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 * 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 */\nexport type SnapHelpers = {\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 onTransaction(\n transaction?: Partial<TransactionOptions>,\n ): Promise<SnapResponseWithInterface>;\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 * @deprecated Use {@link onTransaction} instead.\n */\n sendTransaction(\n transaction?: Partial<TransactionOptions>,\n ): Promise<SnapResponseWithInterface>;\n\n /**\n * Send a signature request to the snap.\n *\n * @param signature - The signature request object. Contains the params from\n * the various signature methods, but has an extra `origin` and `signatureMethod` field.\n * Any missing fields will be filled in with default values.\n * @returns The response.\n */\n onSignature(\n signature?: Partial<SignatureOptions>,\n ): Promise<SnapResponseWithInterface>;\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 onCronjob(cronjob?: Partial<CronjobOptions>): SnapRequest;\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 * @deprecated Use {@link onCronjob} instead.\n */\n runCronjob(cronjob: CronjobOptions): SnapRequest;\n\n /**\n * Get the response from the snap's `onHomePage` method.\n *\n * @returns The response.\n */\n onHomePage(): Promise<SnapResponseWithInterface>;\n\n /**\n * Mock a JSON-RPC request. This will cause the snap to respond with the\n * specified response when a request with the specified method is sent.\n *\n * @param mock - The mock options.\n * @param mock.method - The JSON-RPC request method.\n * @param mock.result - The JSON-RPC response, which will be returned when a\n * request with the specified method is sent.\n * @example\n * import { installSnap } from '@metamask/snaps-jest';\n *\n * // In the test\n * const snap = await installSnap();\n * snap.mockJsonRpc({ method: 'eth_accounts', result: ['0x1234'] });\n *\n * // In the Snap\n * const response =\n * await ethereum.request({ method: 'eth_accounts' }); // ['0x1234']\n */\n mockJsonRpc(mock: JsonRpcMockOptions): {\n /**\n * Remove the mock.\n */\n unmock(): void;\n };\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 close(): Promise<void>;\n};\n\n/**\n * Get the helper functions for the Snap.\n *\n * @param snap - The installed Snap.\n * @param snap.snapId - The ID of the Snap.\n * @param snap.store - The Redux store.\n * @param snap.executionService - The execution service.\n * @param snap.runSaga - The `runSaga` function.\n * @param snap.controllerMessenger - The controller messenger.\n * @param snap.options - The simulation options.\n * @returns The Snap helpers.\n */\nexport function getHelpers({\n snapId,\n store,\n executionService,\n runSaga,\n controllerMessenger,\n options,\n}: InstalledSnap & { options: SimulationOptions }): SnapHelpers {\n const onTransaction = async (\n request: TransactionOptions,\n ): Promise<SnapResponseWithInterface> => {\n log('Sending transaction %o.', request);\n\n const {\n origin: transactionOrigin,\n chainId,\n ...transaction\n } = create(request, TransactionOptionsStruct);\n\n const response = await handleRequest({\n snapId,\n store,\n executionService,\n runSaga,\n controllerMessenger,\n handler: HandlerType.OnTransaction,\n request: {\n method: '',\n params: {\n chainId,\n transaction,\n transactionOrigin,\n },\n },\n });\n\n assertIsResponseWithInterface(response);\n\n return response;\n };\n\n const onCronjob = (request: CronjobOptions) => {\n log('Running cronjob %o.', options);\n\n return handleRequest({\n snapId,\n store,\n executionService,\n controllerMessenger,\n runSaga,\n handler: HandlerType.OnCronjob,\n request,\n });\n };\n\n return {\n request: (request) => {\n log('Sending request %o.', request);\n\n return handleRequest({\n snapId,\n store,\n executionService,\n controllerMessenger,\n runSaga,\n handler: HandlerType.OnRpcRequest,\n request,\n });\n },\n\n onTransaction,\n sendTransaction: onTransaction,\n\n onSignature: async (\n request: unknown,\n ): Promise<SnapResponseWithInterface> => {\n log('Requesting signature %o.', request);\n\n const { origin: signatureOrigin, ...signature } = create(\n request,\n SignatureOptionsStruct,\n );\n\n const response = await handleRequest({\n snapId,\n store,\n executionService,\n controllerMessenger,\n runSaga,\n handler: HandlerType.OnSignature,\n request: {\n method: '',\n params: {\n signature,\n signatureOrigin,\n },\n },\n });\n\n assertIsResponseWithInterface(response);\n\n return response;\n },\n\n onCronjob,\n runCronjob: onCronjob,\n\n onHomePage: async (): Promise<SnapResponseWithInterface> => {\n log('Rendering home page.');\n\n const response = await handleRequest({\n snapId,\n store,\n executionService,\n controllerMessenger,\n runSaga,\n handler: HandlerType.OnHomePage,\n request: {\n method: '',\n },\n });\n\n assertIsResponseWithInterface(response);\n\n return response;\n },\n\n mockJsonRpc(mock: JsonRpcMockOptions) {\n log('Mocking JSON-RPC request %o.', mock);\n\n const { method, result } = create(mock, JsonRpcMockOptionsStruct);\n store.dispatch(addJsonRpcMock({ method, result }));\n\n return {\n unmock() {\n log('Unmocking JSON-RPC request %o.', mock);\n\n store.dispatch(removeJsonRpcMock(method));\n },\n };\n },\n\n close: async () => {\n log('Closing execution service.');\n await executionService.terminateAllSnaps();\n },\n };\n}\n"]}
@@ -0,0 +1,128 @@
1
+ import type { SimulationOptions } from "./options.cjs";
2
+ import type { InstalledSnap } from "./simulation.cjs";
3
+ import type { CronjobOptions, JsonRpcMockOptions, RequestOptions, SignatureOptions, SnapRequest, SnapResponseWithInterface, TransactionOptions } from "./types.cjs";
4
+ /**
5
+ * This is the main entry point to interact with the snap. It is returned by
6
+ * {@link installSnap}, and has methods to send requests to the snap.
7
+ *
8
+ * @example
9
+ * import { installSnap } from '@metamask/snaps-jest';
10
+ *
11
+ * const snap = await installSnap();
12
+ * const response = await snap.request({ method: 'hello' });
13
+ *
14
+ * expect(response).toRespondWith('Hello, world!');
15
+ */
16
+ export type SnapHelpers = {
17
+ /**
18
+ * Send a JSON-RPC request to the snap.
19
+ *
20
+ * @param request - The request. This is similar to a JSON-RPC request, but
21
+ * has an extra `origin` field.
22
+ * @returns The response promise, with extra {@link SnapRequestObject} fields.
23
+ */
24
+ request(request: RequestOptions): SnapRequest;
25
+ /**
26
+ * Send a transaction to the snap.
27
+ *
28
+ * @param transaction - The transaction. This is similar to an Ethereum
29
+ * transaction object, but has an extra `origin` field. Any missing fields
30
+ * will be filled in with default values.
31
+ * @returns The response.
32
+ */
33
+ onTransaction(transaction?: Partial<TransactionOptions>): Promise<SnapResponseWithInterface>;
34
+ /**
35
+ * Send a transaction to the snap.
36
+ *
37
+ * @param transaction - The transaction. This is similar to an Ethereum
38
+ * transaction object, but has an extra `origin` field. Any missing fields
39
+ * will be filled in with default values.
40
+ * @returns The response.
41
+ * @deprecated Use {@link onTransaction} instead.
42
+ */
43
+ sendTransaction(transaction?: Partial<TransactionOptions>): Promise<SnapResponseWithInterface>;
44
+ /**
45
+ * Send a signature request to the snap.
46
+ *
47
+ * @param signature - The signature request object. Contains the params from
48
+ * the various signature methods, but has an extra `origin` and `signatureMethod` field.
49
+ * Any missing fields will be filled in with default values.
50
+ * @returns The response.
51
+ */
52
+ onSignature(signature?: Partial<SignatureOptions>): Promise<SnapResponseWithInterface>;
53
+ /**
54
+ * Run a cronjob in the snap. This is similar to {@link request}, but the
55
+ * request will be sent to the `onCronjob` method of the snap.
56
+ *
57
+ * @param cronjob - The cronjob request. This is similar to a JSON-RPC
58
+ * request, and is normally specified in the snap manifest, under the
59
+ * `endowment:cronjob` permission.
60
+ * @returns The response promise, with extra {@link SnapRequestObject} fields.
61
+ */
62
+ onCronjob(cronjob?: Partial<CronjobOptions>): SnapRequest;
63
+ /**
64
+ * Run a cronjob in the snap. This is similar to {@link request}, but the
65
+ * request will be sent to the `onCronjob` method of the snap.
66
+ *
67
+ * @param cronjob - The cronjob request. This is similar to a JSON-RPC
68
+ * request, and is normally specified in the snap manifest, under the
69
+ * `endowment:cronjob` permission.
70
+ * @returns The response promise, with extra {@link SnapRequestObject} fields.
71
+ * @deprecated Use {@link onCronjob} instead.
72
+ */
73
+ runCronjob(cronjob: CronjobOptions): SnapRequest;
74
+ /**
75
+ * Get the response from the snap's `onHomePage` method.
76
+ *
77
+ * @returns The response.
78
+ */
79
+ onHomePage(): Promise<SnapResponseWithInterface>;
80
+ /**
81
+ * Mock a JSON-RPC request. This will cause the snap to respond with the
82
+ * specified response when a request with the specified method is sent.
83
+ *
84
+ * @param mock - The mock options.
85
+ * @param mock.method - The JSON-RPC request method.
86
+ * @param mock.result - The JSON-RPC response, which will be returned when a
87
+ * request with the specified method is sent.
88
+ * @example
89
+ * import { installSnap } from '@metamask/snaps-jest';
90
+ *
91
+ * // In the test
92
+ * const snap = await installSnap();
93
+ * snap.mockJsonRpc({ method: 'eth_accounts', result: ['0x1234'] });
94
+ *
95
+ * // In the Snap
96
+ * const response =
97
+ * await ethereum.request({ method: 'eth_accounts' }); // ['0x1234']
98
+ */
99
+ mockJsonRpc(mock: JsonRpcMockOptions): {
100
+ /**
101
+ * Remove the mock.
102
+ */
103
+ unmock(): void;
104
+ };
105
+ /**
106
+ * Close the page running the snap. This is mainly useful for cleaning up
107
+ * the test environment, and calling it is not strictly necessary.
108
+ *
109
+ * @returns A promise that resolves when the page is closed.
110
+ */
111
+ close(): Promise<void>;
112
+ };
113
+ /**
114
+ * Get the helper functions for the Snap.
115
+ *
116
+ * @param snap - The installed Snap.
117
+ * @param snap.snapId - The ID of the Snap.
118
+ * @param snap.store - The Redux store.
119
+ * @param snap.executionService - The execution service.
120
+ * @param snap.runSaga - The `runSaga` function.
121
+ * @param snap.controllerMessenger - The controller messenger.
122
+ * @param snap.options - The simulation options.
123
+ * @returns The Snap helpers.
124
+ */
125
+ export declare function getHelpers({ snapId, store, executionService, runSaga, controllerMessenger, options, }: InstalledSnap & {
126
+ options: SimulationOptions;
127
+ }): SnapHelpers;
128
+ //# sourceMappingURL=helpers.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.cts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,sBAAkB;AAEnD,OAAO,KAAK,EAAE,aAAa,EAAE,yBAAqB;AAQlD,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,yBAAyB,EACzB,kBAAkB,EACnB,oBAAgB;AAIjB;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB;;;;;;OAMG;IACH,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,WAAW,CAAC;IAE9C;;;;;;;OAOG;IACH,aAAa,CACX,WAAW,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GACxC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAEtC;;;;;;;;OAQG;IACH,eAAe,CACb,WAAW,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GACxC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAEtC;;;;;;;OAOG;IACH,WAAW,CACT,SAAS,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,GACpC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAEtC;;;;;;;;OAQG;IACH,SAAS,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,WAAW,CAAC;IAE1D;;;;;;;;;OASG;IACH,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,WAAW,CAAC;IAEjD;;;;OAIG;IACH,UAAU,IAAI,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAEjD;;;;;;;;;;;;;;;;;;OAkBG;IACH,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG;QACrC;;WAEG;QACH,MAAM,IAAI,IAAI,CAAC;KAChB,CAAC;IAEF;;;;;OAKG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,KAAK,EACL,gBAAgB,EAChB,OAAO,EACP,mBAAmB,EACnB,OAAO,GACR,EAAE,aAAa,GAAG;IAAE,OAAO,EAAE,iBAAiB,CAAA;CAAE,GAAG,WAAW,CA4I9D"}
@@ -0,0 +1,128 @@
1
+ import type { SimulationOptions } from "./options.mjs";
2
+ import type { InstalledSnap } from "./simulation.mjs";
3
+ import type { CronjobOptions, JsonRpcMockOptions, RequestOptions, SignatureOptions, SnapRequest, SnapResponseWithInterface, TransactionOptions } from "./types.mjs";
4
+ /**
5
+ * This is the main entry point to interact with the snap. It is returned by
6
+ * {@link installSnap}, and has methods to send requests to the snap.
7
+ *
8
+ * @example
9
+ * import { installSnap } from '@metamask/snaps-jest';
10
+ *
11
+ * const snap = await installSnap();
12
+ * const response = await snap.request({ method: 'hello' });
13
+ *
14
+ * expect(response).toRespondWith('Hello, world!');
15
+ */
16
+ export type SnapHelpers = {
17
+ /**
18
+ * Send a JSON-RPC request to the snap.
19
+ *
20
+ * @param request - The request. This is similar to a JSON-RPC request, but
21
+ * has an extra `origin` field.
22
+ * @returns The response promise, with extra {@link SnapRequestObject} fields.
23
+ */
24
+ request(request: RequestOptions): SnapRequest;
25
+ /**
26
+ * Send a transaction to the snap.
27
+ *
28
+ * @param transaction - The transaction. This is similar to an Ethereum
29
+ * transaction object, but has an extra `origin` field. Any missing fields
30
+ * will be filled in with default values.
31
+ * @returns The response.
32
+ */
33
+ onTransaction(transaction?: Partial<TransactionOptions>): Promise<SnapResponseWithInterface>;
34
+ /**
35
+ * Send a transaction to the snap.
36
+ *
37
+ * @param transaction - The transaction. This is similar to an Ethereum
38
+ * transaction object, but has an extra `origin` field. Any missing fields
39
+ * will be filled in with default values.
40
+ * @returns The response.
41
+ * @deprecated Use {@link onTransaction} instead.
42
+ */
43
+ sendTransaction(transaction?: Partial<TransactionOptions>): Promise<SnapResponseWithInterface>;
44
+ /**
45
+ * Send a signature request to the snap.
46
+ *
47
+ * @param signature - The signature request object. Contains the params from
48
+ * the various signature methods, but has an extra `origin` and `signatureMethod` field.
49
+ * Any missing fields will be filled in with default values.
50
+ * @returns The response.
51
+ */
52
+ onSignature(signature?: Partial<SignatureOptions>): Promise<SnapResponseWithInterface>;
53
+ /**
54
+ * Run a cronjob in the snap. This is similar to {@link request}, but the
55
+ * request will be sent to the `onCronjob` method of the snap.
56
+ *
57
+ * @param cronjob - The cronjob request. This is similar to a JSON-RPC
58
+ * request, and is normally specified in the snap manifest, under the
59
+ * `endowment:cronjob` permission.
60
+ * @returns The response promise, with extra {@link SnapRequestObject} fields.
61
+ */
62
+ onCronjob(cronjob?: Partial<CronjobOptions>): SnapRequest;
63
+ /**
64
+ * Run a cronjob in the snap. This is similar to {@link request}, but the
65
+ * request will be sent to the `onCronjob` method of the snap.
66
+ *
67
+ * @param cronjob - The cronjob request. This is similar to a JSON-RPC
68
+ * request, and is normally specified in the snap manifest, under the
69
+ * `endowment:cronjob` permission.
70
+ * @returns The response promise, with extra {@link SnapRequestObject} fields.
71
+ * @deprecated Use {@link onCronjob} instead.
72
+ */
73
+ runCronjob(cronjob: CronjobOptions): SnapRequest;
74
+ /**
75
+ * Get the response from the snap's `onHomePage` method.
76
+ *
77
+ * @returns The response.
78
+ */
79
+ onHomePage(): Promise<SnapResponseWithInterface>;
80
+ /**
81
+ * Mock a JSON-RPC request. This will cause the snap to respond with the
82
+ * specified response when a request with the specified method is sent.
83
+ *
84
+ * @param mock - The mock options.
85
+ * @param mock.method - The JSON-RPC request method.
86
+ * @param mock.result - The JSON-RPC response, which will be returned when a
87
+ * request with the specified method is sent.
88
+ * @example
89
+ * import { installSnap } from '@metamask/snaps-jest';
90
+ *
91
+ * // In the test
92
+ * const snap = await installSnap();
93
+ * snap.mockJsonRpc({ method: 'eth_accounts', result: ['0x1234'] });
94
+ *
95
+ * // In the Snap
96
+ * const response =
97
+ * await ethereum.request({ method: 'eth_accounts' }); // ['0x1234']
98
+ */
99
+ mockJsonRpc(mock: JsonRpcMockOptions): {
100
+ /**
101
+ * Remove the mock.
102
+ */
103
+ unmock(): void;
104
+ };
105
+ /**
106
+ * Close the page running the snap. This is mainly useful for cleaning up
107
+ * the test environment, and calling it is not strictly necessary.
108
+ *
109
+ * @returns A promise that resolves when the page is closed.
110
+ */
111
+ close(): Promise<void>;
112
+ };
113
+ /**
114
+ * Get the helper functions for the Snap.
115
+ *
116
+ * @param snap - The installed Snap.
117
+ * @param snap.snapId - The ID of the Snap.
118
+ * @param snap.store - The Redux store.
119
+ * @param snap.executionService - The execution service.
120
+ * @param snap.runSaga - The `runSaga` function.
121
+ * @param snap.controllerMessenger - The controller messenger.
122
+ * @param snap.options - The simulation options.
123
+ * @returns The Snap helpers.
124
+ */
125
+ export declare function getHelpers({ snapId, store, executionService, runSaga, controllerMessenger, options, }: InstalledSnap & {
126
+ options: SimulationOptions;
127
+ }): SnapHelpers;
128
+ //# sourceMappingURL=helpers.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.mts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,sBAAkB;AAEnD,OAAO,KAAK,EAAE,aAAa,EAAE,yBAAqB;AAQlD,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,yBAAyB,EACzB,kBAAkB,EACnB,oBAAgB;AAIjB;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB;;;;;;OAMG;IACH,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,WAAW,CAAC;IAE9C;;;;;;;OAOG;IACH,aAAa,CACX,WAAW,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GACxC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAEtC;;;;;;;;OAQG;IACH,eAAe,CACb,WAAW,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GACxC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAEtC;;;;;;;OAOG;IACH,WAAW,CACT,SAAS,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,GACpC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAEtC;;;;;;;;OAQG;IACH,SAAS,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,WAAW,CAAC;IAE1D;;;;;;;;;OASG;IACH,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,WAAW,CAAC;IAEjD;;;;OAIG;IACH,UAAU,IAAI,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAEjD;;;;;;;;;;;;;;;;;;OAkBG;IACH,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG;QACrC;;WAEG;QACH,MAAM,IAAI,IAAI,CAAC;KAChB,CAAC;IAEF;;;;;OAKG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,KAAK,EACL,gBAAgB,EAChB,OAAO,EACP,mBAAmB,EACnB,OAAO,GACR,EAAE,aAAa,GAAG;IAAE,OAAO,EAAE,iBAAiB,CAAA;CAAE,GAAG,WAAW,CA4I9D"}
@@ -0,0 +1,127 @@
1
+ import { HandlerType } from "@metamask/snaps-utils";
2
+ import { create } from "@metamask/superstruct";
3
+ import { createModuleLogger } from "@metamask/utils";
4
+ import { rootLogger } from "./logger.mjs";
5
+ import { handleRequest } from "./request.mjs";
6
+ import { addJsonRpcMock, removeJsonRpcMock } from "./store/index.mjs";
7
+ import { assertIsResponseWithInterface, JsonRpcMockOptionsStruct, SignatureOptionsStruct, TransactionOptionsStruct } from "./structs.mjs";
8
+ const log = createModuleLogger(rootLogger, 'helpers');
9
+ /**
10
+ * Get the helper functions for the Snap.
11
+ *
12
+ * @param snap - The installed Snap.
13
+ * @param snap.snapId - The ID of the Snap.
14
+ * @param snap.store - The Redux store.
15
+ * @param snap.executionService - The execution service.
16
+ * @param snap.runSaga - The `runSaga` function.
17
+ * @param snap.controllerMessenger - The controller messenger.
18
+ * @param snap.options - The simulation options.
19
+ * @returns The Snap helpers.
20
+ */
21
+ export function getHelpers({ snapId, store, executionService, runSaga, controllerMessenger, options, }) {
22
+ const onTransaction = async (request) => {
23
+ log('Sending transaction %o.', request);
24
+ const { origin: transactionOrigin, chainId, ...transaction } = create(request, TransactionOptionsStruct);
25
+ const response = await handleRequest({
26
+ snapId,
27
+ store,
28
+ executionService,
29
+ runSaga,
30
+ controllerMessenger,
31
+ handler: HandlerType.OnTransaction,
32
+ request: {
33
+ method: '',
34
+ params: {
35
+ chainId,
36
+ transaction,
37
+ transactionOrigin,
38
+ },
39
+ },
40
+ });
41
+ assertIsResponseWithInterface(response);
42
+ return response;
43
+ };
44
+ const onCronjob = (request) => {
45
+ log('Running cronjob %o.', options);
46
+ return handleRequest({
47
+ snapId,
48
+ store,
49
+ executionService,
50
+ controllerMessenger,
51
+ runSaga,
52
+ handler: HandlerType.OnCronjob,
53
+ request,
54
+ });
55
+ };
56
+ return {
57
+ request: (request) => {
58
+ log('Sending request %o.', request);
59
+ return handleRequest({
60
+ snapId,
61
+ store,
62
+ executionService,
63
+ controllerMessenger,
64
+ runSaga,
65
+ handler: HandlerType.OnRpcRequest,
66
+ request,
67
+ });
68
+ },
69
+ onTransaction,
70
+ sendTransaction: onTransaction,
71
+ onSignature: async (request) => {
72
+ log('Requesting signature %o.', request);
73
+ const { origin: signatureOrigin, ...signature } = create(request, SignatureOptionsStruct);
74
+ const response = await handleRequest({
75
+ snapId,
76
+ store,
77
+ executionService,
78
+ controllerMessenger,
79
+ runSaga,
80
+ handler: HandlerType.OnSignature,
81
+ request: {
82
+ method: '',
83
+ params: {
84
+ signature,
85
+ signatureOrigin,
86
+ },
87
+ },
88
+ });
89
+ assertIsResponseWithInterface(response);
90
+ return response;
91
+ },
92
+ onCronjob,
93
+ runCronjob: onCronjob,
94
+ onHomePage: async () => {
95
+ log('Rendering home page.');
96
+ const response = await handleRequest({
97
+ snapId,
98
+ store,
99
+ executionService,
100
+ controllerMessenger,
101
+ runSaga,
102
+ handler: HandlerType.OnHomePage,
103
+ request: {
104
+ method: '',
105
+ },
106
+ });
107
+ assertIsResponseWithInterface(response);
108
+ return response;
109
+ },
110
+ mockJsonRpc(mock) {
111
+ log('Mocking JSON-RPC request %o.', mock);
112
+ const { method, result } = create(mock, JsonRpcMockOptionsStruct);
113
+ store.dispatch(addJsonRpcMock({ method, result }));
114
+ return {
115
+ unmock() {
116
+ log('Unmocking JSON-RPC request %o.', mock);
117
+ store.dispatch(removeJsonRpcMock(method));
118
+ },
119
+ };
120
+ },
121
+ close: async () => {
122
+ log('Closing execution service.');
123
+ await executionService.terminateAllSnaps();
124
+ },
125
+ };
126
+ }
127
+ //# sourceMappingURL=helpers.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.mjs","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import { HandlerType } from '@metamask/snaps-utils';\nimport { create } from '@metamask/superstruct';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { rootLogger } from './logger';\nimport type { SimulationOptions } from './options';\nimport { handleRequest } from './request';\nimport type { InstalledSnap } from './simulation';\nimport { addJsonRpcMock, removeJsonRpcMock } from './store';\nimport {\n assertIsResponseWithInterface,\n JsonRpcMockOptionsStruct,\n SignatureOptionsStruct,\n TransactionOptionsStruct,\n} from './structs';\nimport type {\n CronjobOptions,\n JsonRpcMockOptions,\n RequestOptions,\n SignatureOptions,\n SnapRequest,\n SnapResponseWithInterface,\n TransactionOptions,\n} from './types';\n\nconst log = createModuleLogger(rootLogger, 'helpers');\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 * 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 */\nexport type SnapHelpers = {\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 onTransaction(\n transaction?: Partial<TransactionOptions>,\n ): Promise<SnapResponseWithInterface>;\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 * @deprecated Use {@link onTransaction} instead.\n */\n sendTransaction(\n transaction?: Partial<TransactionOptions>,\n ): Promise<SnapResponseWithInterface>;\n\n /**\n * Send a signature request to the snap.\n *\n * @param signature - The signature request object. Contains the params from\n * the various signature methods, but has an extra `origin` and `signatureMethod` field.\n * Any missing fields will be filled in with default values.\n * @returns The response.\n */\n onSignature(\n signature?: Partial<SignatureOptions>,\n ): Promise<SnapResponseWithInterface>;\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 onCronjob(cronjob?: Partial<CronjobOptions>): SnapRequest;\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 * @deprecated Use {@link onCronjob} instead.\n */\n runCronjob(cronjob: CronjobOptions): SnapRequest;\n\n /**\n * Get the response from the snap's `onHomePage` method.\n *\n * @returns The response.\n */\n onHomePage(): Promise<SnapResponseWithInterface>;\n\n /**\n * Mock a JSON-RPC request. This will cause the snap to respond with the\n * specified response when a request with the specified method is sent.\n *\n * @param mock - The mock options.\n * @param mock.method - The JSON-RPC request method.\n * @param mock.result - The JSON-RPC response, which will be returned when a\n * request with the specified method is sent.\n * @example\n * import { installSnap } from '@metamask/snaps-jest';\n *\n * // In the test\n * const snap = await installSnap();\n * snap.mockJsonRpc({ method: 'eth_accounts', result: ['0x1234'] });\n *\n * // In the Snap\n * const response =\n * await ethereum.request({ method: 'eth_accounts' }); // ['0x1234']\n */\n mockJsonRpc(mock: JsonRpcMockOptions): {\n /**\n * Remove the mock.\n */\n unmock(): void;\n };\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 close(): Promise<void>;\n};\n\n/**\n * Get the helper functions for the Snap.\n *\n * @param snap - The installed Snap.\n * @param snap.snapId - The ID of the Snap.\n * @param snap.store - The Redux store.\n * @param snap.executionService - The execution service.\n * @param snap.runSaga - The `runSaga` function.\n * @param snap.controllerMessenger - The controller messenger.\n * @param snap.options - The simulation options.\n * @returns The Snap helpers.\n */\nexport function getHelpers({\n snapId,\n store,\n executionService,\n runSaga,\n controllerMessenger,\n options,\n}: InstalledSnap & { options: SimulationOptions }): SnapHelpers {\n const onTransaction = async (\n request: TransactionOptions,\n ): Promise<SnapResponseWithInterface> => {\n log('Sending transaction %o.', request);\n\n const {\n origin: transactionOrigin,\n chainId,\n ...transaction\n } = create(request, TransactionOptionsStruct);\n\n const response = await handleRequest({\n snapId,\n store,\n executionService,\n runSaga,\n controllerMessenger,\n handler: HandlerType.OnTransaction,\n request: {\n method: '',\n params: {\n chainId,\n transaction,\n transactionOrigin,\n },\n },\n });\n\n assertIsResponseWithInterface(response);\n\n return response;\n };\n\n const onCronjob = (request: CronjobOptions) => {\n log('Running cronjob %o.', options);\n\n return handleRequest({\n snapId,\n store,\n executionService,\n controllerMessenger,\n runSaga,\n handler: HandlerType.OnCronjob,\n request,\n });\n };\n\n return {\n request: (request) => {\n log('Sending request %o.', request);\n\n return handleRequest({\n snapId,\n store,\n executionService,\n controllerMessenger,\n runSaga,\n handler: HandlerType.OnRpcRequest,\n request,\n });\n },\n\n onTransaction,\n sendTransaction: onTransaction,\n\n onSignature: async (\n request: unknown,\n ): Promise<SnapResponseWithInterface> => {\n log('Requesting signature %o.', request);\n\n const { origin: signatureOrigin, ...signature } = create(\n request,\n SignatureOptionsStruct,\n );\n\n const response = await handleRequest({\n snapId,\n store,\n executionService,\n controllerMessenger,\n runSaga,\n handler: HandlerType.OnSignature,\n request: {\n method: '',\n params: {\n signature,\n signatureOrigin,\n },\n },\n });\n\n assertIsResponseWithInterface(response);\n\n return response;\n },\n\n onCronjob,\n runCronjob: onCronjob,\n\n onHomePage: async (): Promise<SnapResponseWithInterface> => {\n log('Rendering home page.');\n\n const response = await handleRequest({\n snapId,\n store,\n executionService,\n controllerMessenger,\n runSaga,\n handler: HandlerType.OnHomePage,\n request: {\n method: '',\n },\n });\n\n assertIsResponseWithInterface(response);\n\n return response;\n },\n\n mockJsonRpc(mock: JsonRpcMockOptions) {\n log('Mocking JSON-RPC request %o.', mock);\n\n const { method, result } = create(mock, JsonRpcMockOptionsStruct);\n store.dispatch(addJsonRpcMock({ method, result }));\n\n return {\n unmock() {\n log('Unmocking JSON-RPC request %o.', mock);\n\n store.dispatch(removeJsonRpcMock(method));\n },\n };\n },\n\n close: async () => {\n log('Closing execution service.');\n await executionService.terminateAllSnaps();\n },\n };\n}\n"]}
package/dist/index.cjs CHANGED
@@ -16,6 +16,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./constants.cjs"), exports);
18
18
  __exportStar(require("./controllers.cjs"), exports);
19
+ __exportStar(require("./helpers.cjs"), exports);
19
20
  __exportStar(require("./interface.cjs"), exports);
20
21
  __exportStar(require("./options.cjs"), exports);
21
22
  __exportStar(require("./request.cjs"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAA4B;AAC5B,oDAA8B;AAC9B,kDAA4B;AAC5B,gDAA0B;AAC1B,gDAA0B;AAC1B,mDAA6B;AAC7B,oDAAwB;AACxB,gDAA0B;AAC1B,8CAAwB;AACxB,mDAA6B","sourcesContent":["export * from './constants';\nexport * from './controllers';\nexport * from './interface';\nexport * from './options';\nexport * from './request';\nexport * from './simulation';\nexport * from './store';\nexport * from './structs';\nexport * from './types';\nexport * from './validation';\n"]}
1
+ {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAA4B;AAC5B,oDAA8B;AAC9B,gDAA0B;AAC1B,kDAA4B;AAC5B,gDAA0B;AAC1B,gDAA0B;AAC1B,mDAA6B;AAC7B,oDAAwB;AACxB,gDAA0B;AAC1B,8CAAwB;AACxB,mDAA6B","sourcesContent":["export * from './constants';\nexport * from './controllers';\nexport * from './helpers';\nexport * from './interface';\nexport * from './options';\nexport * from './request';\nexport * from './simulation';\nexport * from './store';\nexport * from './structs';\nexport * from './types';\nexport * from './validation';\n"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from "./constants.cjs";
2
2
  export * from "./controllers.cjs";
3
+ export * from "./helpers.cjs";
3
4
  export * from "./interface.cjs";
4
5
  export * from "./options.cjs";
5
6
  export * from "./request.cjs";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gCAA4B;AAC5B,kCAA8B;AAC9B,gCAA4B;AAC5B,8BAA0B;AAC1B,8BAA0B;AAC1B,iCAA6B;AAC7B,kCAAwB;AACxB,8BAA0B;AAC1B,4BAAwB;AACxB,iCAA6B"}
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gCAA4B;AAC5B,kCAA8B;AAC9B,8BAA0B;AAC1B,gCAA4B;AAC5B,8BAA0B;AAC1B,8BAA0B;AAC1B,iCAA6B;AAC7B,kCAAwB;AACxB,8BAA0B;AAC1B,4BAAwB;AACxB,iCAA6B"}
package/dist/index.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from "./constants.mjs";
2
2
  export * from "./controllers.mjs";
3
+ export * from "./helpers.mjs";
3
4
  export * from "./interface.mjs";
4
5
  export * from "./options.mjs";
5
6
  export * from "./request.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gCAA4B;AAC5B,kCAA8B;AAC9B,gCAA4B;AAC5B,8BAA0B;AAC1B,8BAA0B;AAC1B,iCAA6B;AAC7B,kCAAwB;AACxB,8BAA0B;AAC1B,4BAAwB;AACxB,iCAA6B"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gCAA4B;AAC5B,kCAA8B;AAC9B,8BAA0B;AAC1B,gCAA4B;AAC5B,8BAA0B;AAC1B,8BAA0B;AAC1B,iCAA6B;AAC7B,kCAAwB;AACxB,8BAA0B;AAC1B,4BAAwB;AACxB,iCAA6B"}