@metamask-previews/eth-snap-keyring 4.3.3-38c4bd5 → 4.3.6-d5a036e

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
@@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [4.3.6]
11
+
12
+ ### Changed
13
+
14
+ - Bump `sinon` and `@types/sinon` to latest versions ([#51](https://github.com/MetaMask/accounts/pull/51))
15
+ - Add `syncpack` and sync dependencies ([#53](https://github.com/metamask/accounts/pull/53))
16
+
17
+ ## [4.3.5]
18
+
19
+ ### Changed
20
+
21
+ - Bump `@metamask/*` and `@lavamoat/*` dependencies ([#46](https://github.com/MetaMask/accounts/pull/46))
22
+ - Move `deepmerge` to `devDependencies` ([#44](https://github.com/MetaMask/accounts/pull/44))
23
+
24
+ ## [4.3.4]
25
+
26
+ ### Changed
27
+
28
+ - Convert to monorepo
29
+ - Package name does not change (`@metamask/eth-snap-keyring`) and sources have been moved to: `packages/keyring-snap-bridge`.
30
+ - You can find all the changes [here](https://github.com/MetaMask/accounts/compare/6da58b4...38794aa).
31
+
10
32
  ## [4.3.3]
11
33
 
12
34
  ### Changed
@@ -320,7 +342,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
320
342
 
321
343
  - Initial release.
322
344
 
323
- [Unreleased]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@4.3.3...HEAD
345
+ [Unreleased]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@4.3.6...HEAD
346
+ [4.3.6]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@4.3.5...@metamask/eth-snap-keyring@4.3.6
347
+ [4.3.5]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@4.3.4...@metamask/eth-snap-keyring@4.3.5
348
+ [4.3.4]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@4.3.3...@metamask/eth-snap-keyring@4.3.4
324
349
  [4.3.3]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@4.3.2...@metamask/eth-snap-keyring@4.3.3
325
350
  [4.3.2]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@4.3.1...@metamask/eth-snap-keyring@4.3.2
326
351
  [4.3.1]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@4.3.0...@metamask/eth-snap-keyring@4.3.1
@@ -1 +1 @@
1
- {"version":3,"file":"DeferredPromise.js","sourceRoot":"","sources":["../src/DeferredPromise.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;GAQG;AACH,MAAa,eAAe;IAO1B;QAJA,YAAO,GAA8C,SAAgB,CAAC;QAEtE,WAAM,GAA2B,SAAgB,CAAC;QAGhD,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC7C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;YACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACvB,CAAC,CAAC,CAAC;QAEH,mEAAmE;QACnE,qDAAqD;QACrD,0BAA0B;QAC1B,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;YACjC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;SAC/C;IACH,CAAC;CACF;AApBD,0CAoBC","sourcesContent":["/**\n * A deferred promise can be resolved by a caller different from the one who\n * created it.\n *\n * Example:\n * - \"A\" creates a deferred promise \"P\", adds it to a list, and awaits it\n * - \"B\" gets \"P\" from the list and resolves it\n * - \"A\" gets the resolved value\n */\nexport class DeferredPromise<Type> {\n promise: Promise<Type>;\n\n resolve: (value: Type | PromiseLike<Type>) => void = undefined as any;\n\n reject: (reason?: any) => void = undefined as any;\n\n constructor() {\n this.promise = new Promise((resolve, reject) => {\n this.resolve = resolve;\n this.reject = reject;\n });\n\n // This is a sanity check to make sure that the promise constructor\n // actually set the `resolve` and `reject` functions.\n /* istanbul ignore next */\n if (!this.resolve || !this.reject) {\n throw new Error('Promise constructor failed');\n }\n }\n}\n"]}
1
+ {"version":3,"file":"DeferredPromise.js","sourceRoot":"","sources":["../src/DeferredPromise.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;GAQG;AACH,MAAa,eAAe;IAO1B;QAJA,YAAO,GAA8C,SAAgB,CAAC;QAEtE,WAAM,GAA2B,SAAgB,CAAC;QAGhD,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC7C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;YACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACvB,CAAC,CAAC,CAAC;QAEH,mEAAmE;QACnE,qDAAqD;QACrD,0BAA0B;QAC1B,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;CACF;AApBD,0CAoBC","sourcesContent":["/**\n * A deferred promise can be resolved by a caller different from the one who\n * created it.\n *\n * Example:\n * - \"A\" creates a deferred promise \"P\", adds it to a list, and awaits it\n * - \"B\" gets \"P\" from the list and resolves it\n * - \"A\" gets the resolved value\n */\nexport class DeferredPromise<Type> {\n promise: Promise<Type>;\n\n resolve: (value: Type | PromiseLike<Type>) => void = undefined as any;\n\n reject: (reason?: any) => void = undefined as any;\n\n constructor() {\n this.promise = new Promise((resolve, reject) => {\n this.resolve = resolve;\n this.reject = reject;\n });\n\n // This is a sanity check to make sure that the promise constructor\n // actually set the `resolve` and `reject` functions.\n /* istanbul ignore next */\n if (!this.resolve || !this.reject) {\n throw new Error('Promise constructor failed');\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"KeyringSnapControllerClient.js","sourceRoot":"","sources":["../src/KeyringSnapControllerClient.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,uDAAmE;AAOnE;;;GAGG;AACH,MAAM,oBAAoB;IASxB;;;;;;;OAOG;IACH,YACE,UAAe,EACf,MAAc,EACd,MAAc,EACd,OAAoB;QApBtB,+CAAgB;QAEhB,+CAAgB;QAEhB,mDAA4B;QAE5B,gDAAsB;QAgBpB,uBAAA,IAAI,oCAAe,UAAU,MAAA,CAAC;QAC9B,uBAAA,IAAI,gCAAW,MAAM,MAAA,CAAC;QACtB,uBAAA,IAAI,gCAAW,MAAM,MAAA,CAAC;QACtB,uBAAA,IAAI,iCAAY,OAAO,MAAA,CAAC;IAC1B,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,IAAI,CAAC,OAAuB;QAChC,OAAO,uBAAA,IAAI,wCAAY,CAAC,aAAa,CAAC;YACpC,MAAM,EAAE,uBAAA,IAAI,oCAAQ;YACpB,MAAM,EAAE,uBAAA,IAAI,oCAAQ;YACpB,OAAO,EAAE,uBAAA,IAAI,qCAAS;YACtB,OAAO;SACR,CAAkB,CAAC;IACtB,CAAC;CACF;;AAED;;;GAGG;AACH,MAAa,2BAA4B,SAAQ,2BAAa;IAG5D;;;;;;;;;;;;OAYG;IACH,YAAY,EACV,UAAU,EACV,MAAM,GAAG,WAAqB,EAC9B,MAAM,GAAG,UAAU,EACnB,OAAO,GAAG,kBAAiC,GAM5C;QACC,KAAK,CAAC,IAAI,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;QA1BvE,0DAA4B;QA2B1B,uBAAA,IAAI,2CAAe,UAAU,MAAA,CAAC;IAChC,CAAC;IAED;;;;;;;OAOG;IACH,UAAU,CAAC,MAAc;QACvB,OAAO,IAAI,2BAA2B,CAAC;YACrC,UAAU,EAAE,uBAAA,IAAI,+CAAY;YAC5B,MAAM;SACP,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,aAAa;QACX,OAAO,uBAAA,IAAI,+CAAY,CAAC;IAC1B,CAAC;CACF;AAtDD,kEAsDC","sourcesContent":["import { KeyringClient, type Sender } from '@metamask/keyring-api';\nimport type { JsonRpcRequest } from '@metamask/keyring-api/dist/JsonRpcRequest';\nimport type { SnapController } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport type { HandlerType } from '@metamask/snaps-utils';\nimport type { Json } from '@metamask/utils';\n\n/**\n * Implementation of the `Sender` interface that can be used to send requests\n * to a snap through a `SnapController`.\n */\nclass SnapControllerSender implements Sender {\n #snapId: SnapId;\n\n #origin: string;\n\n #controller: SnapController;\n\n #handler: HandlerType;\n\n /**\n * Create a new instance of `SnapControllerSender`.\n *\n * @param controller - The `SnapController` instance to send requests to.\n * @param snapId - The ID of the snap to use.\n * @param origin - The sender's origin.\n * @param handler - The handler type.\n */\n constructor(\n controller: any,\n snapId: SnapId,\n origin: string,\n handler: HandlerType,\n ) {\n this.#controller = controller;\n this.#snapId = snapId;\n this.#origin = origin;\n this.#handler = handler;\n }\n\n /**\n * Send a request to the snap and return the response.\n *\n * @param request - JSON-RPC request to send to the snap.\n * @returns A promise that resolves to the response of the request.\n */\n async send(request: JsonRpcRequest): Promise<Json> {\n return this.#controller.handleRequest({\n snapId: this.#snapId,\n origin: this.#origin,\n handler: this.#handler,\n request,\n }) as Promise<Json>;\n }\n}\n\n/**\n * A `KeyringClient` that allows the communication with a snap through the\n * `SnapController`.\n */\nexport class KeyringSnapControllerClient extends KeyringClient {\n #controller: SnapController;\n\n /**\n * Create a new instance of `KeyringSnapControllerClient`.\n *\n * The `handlerType` argument has a hard-coded default `string` value instead\n * of a `HandlerType` value to prevent the `@metamask/snaps-utils` module\n * from being required at runtime.\n *\n * @param args - Constructor arguments.\n * @param args.controller - The `SnapController` instance to use.\n * @param args.snapId - The ID of the snap to use (default: `'undefined'`).\n * @param args.origin - The sender's origin (default: `'metamask'`).\n * @param args.handler - The handler type (default: `'onKeyringRequest'`).\n */\n constructor({\n controller,\n snapId = 'undefined' as SnapId,\n origin = 'metamask',\n handler = 'onKeyringRequest' as HandlerType,\n }: {\n controller: SnapController;\n snapId?: SnapId;\n origin?: string;\n handler?: HandlerType;\n }) {\n super(new SnapControllerSender(controller, snapId, origin, handler));\n this.#controller = controller;\n }\n\n /**\n * Create a new instance of `KeyringSnapControllerClient` with the specified\n * `snapId`.\n *\n * @param snapId - The ID of the snap to use in the new instance.\n * @returns A new instance of `KeyringSnapControllerClient` with the\n * specified snap ID.\n */\n withSnapId(snapId: SnapId): KeyringSnapControllerClient {\n return new KeyringSnapControllerClient({\n controller: this.#controller,\n snapId,\n });\n }\n\n /**\n * Get the `SnapController` instance used by this client.\n *\n * @returns The `SnapController` instance used by this client.\n */\n getController(): SnapController {\n return this.#controller;\n }\n}\n"]}
1
+ {"version":3,"file":"KeyringSnapControllerClient.js","sourceRoot":"","sources":["../src/KeyringSnapControllerClient.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,uDAAmE;AAOnE;;;GAGG;AACH,MAAM,oBAAoB;IASxB;;;;;;;OAOG;IACH,YACE,UAAe,EACf,MAAc,EACd,MAAc,EACd,OAAoB;QApBb,+CAAgB;QAEhB,+CAAgB;QAEhB,mDAA4B;QAE5B,gDAAsB;QAgB7B,uBAAA,IAAI,oCAAe,UAAU,MAAA,CAAC;QAC9B,uBAAA,IAAI,gCAAW,MAAM,MAAA,CAAC;QACtB,uBAAA,IAAI,gCAAW,MAAM,MAAA,CAAC;QACtB,uBAAA,IAAI,iCAAY,OAAO,MAAA,CAAC;IAC1B,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,IAAI,CAAC,OAAuB;QAChC,OAAO,uBAAA,IAAI,wCAAY,CAAC,aAAa,CAAC;YACpC,MAAM,EAAE,uBAAA,IAAI,oCAAQ;YACpB,MAAM,EAAE,uBAAA,IAAI,oCAAQ;YACpB,OAAO,EAAE,uBAAA,IAAI,qCAAS;YACtB,OAAO;SACR,CAAkB,CAAC;IACtB,CAAC;CACF;;AAED;;;GAGG;AACH,MAAa,2BAA4B,SAAQ,2BAAa;IAG5D;;;;;;;;;;;;OAYG;IACH,YAAY,EACV,UAAU,EACV,MAAM,GAAG,WAAqB,EAC9B,MAAM,GAAG,UAAU,EACnB,OAAO,GAAG,kBAAiC,GAM5C;QACC,KAAK,CAAC,IAAI,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;QA1B9D,0DAA4B;QA2BnC,uBAAA,IAAI,2CAAe,UAAU,MAAA,CAAC;IAChC,CAAC;IAED;;;;;;;OAOG;IACH,UAAU,CAAC,MAAc;QACvB,OAAO,IAAI,2BAA2B,CAAC;YACrC,UAAU,EAAE,uBAAA,IAAI,+CAAY;YAC5B,MAAM;SACP,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,aAAa;QACX,OAAO,uBAAA,IAAI,+CAAY,CAAC;IAC1B,CAAC;CACF;AAtDD,kEAsDC","sourcesContent":["import { KeyringClient, type Sender } from '@metamask/keyring-api';\nimport type { JsonRpcRequest } from '@metamask/keyring-api/dist/JsonRpcRequest';\nimport type { SnapController } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport type { HandlerType } from '@metamask/snaps-utils';\nimport type { Json } from '@metamask/utils';\n\n/**\n * Implementation of the `Sender` interface that can be used to send requests\n * to a snap through a `SnapController`.\n */\nclass SnapControllerSender implements Sender {\n readonly #snapId: SnapId;\n\n readonly #origin: string;\n\n readonly #controller: SnapController;\n\n readonly #handler: HandlerType;\n\n /**\n * Create a new instance of `SnapControllerSender`.\n *\n * @param controller - The `SnapController` instance to send requests to.\n * @param snapId - The ID of the snap to use.\n * @param origin - The sender's origin.\n * @param handler - The handler type.\n */\n constructor(\n controller: any,\n snapId: SnapId,\n origin: string,\n handler: HandlerType,\n ) {\n this.#controller = controller;\n this.#snapId = snapId;\n this.#origin = origin;\n this.#handler = handler;\n }\n\n /**\n * Send a request to the snap and return the response.\n *\n * @param request - JSON-RPC request to send to the snap.\n * @returns A promise that resolves to the response of the request.\n */\n async send(request: JsonRpcRequest): Promise<Json> {\n return this.#controller.handleRequest({\n snapId: this.#snapId,\n origin: this.#origin,\n handler: this.#handler,\n request,\n }) as Promise<Json>;\n }\n}\n\n/**\n * A `KeyringClient` that allows the communication with a snap through the\n * `SnapController`.\n */\nexport class KeyringSnapControllerClient extends KeyringClient {\n readonly #controller: SnapController;\n\n /**\n * Create a new instance of `KeyringSnapControllerClient`.\n *\n * The `handlerType` argument has a hard-coded default `string` value instead\n * of a `HandlerType` value to prevent the `@metamask/snaps-utils` module\n * from being required at runtime.\n *\n * @param args - Constructor arguments.\n * @param args.controller - The `SnapController` instance to use.\n * @param args.snapId - The ID of the snap to use (default: `'undefined'`).\n * @param args.origin - The sender's origin (default: `'metamask'`).\n * @param args.handler - The handler type (default: `'onKeyringRequest'`).\n */\n constructor({\n controller,\n snapId = 'undefined' as SnapId,\n origin = 'metamask',\n handler = 'onKeyringRequest' as HandlerType,\n }: {\n controller: SnapController;\n snapId?: SnapId;\n origin?: string;\n handler?: HandlerType;\n }) {\n super(new SnapControllerSender(controller, snapId, origin, handler));\n this.#controller = controller;\n }\n\n /**\n * Create a new instance of `KeyringSnapControllerClient` with the specified\n * `snapId`.\n *\n * @param snapId - The ID of the snap to use in the new instance.\n * @returns A new instance of `KeyringSnapControllerClient` with the\n * specified snap ID.\n */\n withSnapId(snapId: SnapId): KeyringSnapControllerClient {\n return new KeyringSnapControllerClient({\n controller: this.#controller,\n snapId,\n });\n }\n\n /**\n * Get the `SnapController` instance used by this client.\n *\n * @returns The `SnapController` instance used by this client.\n */\n getController(): SnapController {\n return this.#controller;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"SnapIdMap.js","sourceRoot":"","sources":["../src/SnapIdMap.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAEA,6DAA0D;AAE1D;;GAEG;AACH,MAAa,kBAAmB,SAAQ,KAAK;IAW3C;;;;;OAKG;IACH,YAAY,MAAc,EAAE,GAAW;QACrC,KAAK,CAAC,SAAS,MAAM,4BAA4B,GAAG,GAAG,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;CACF;AAvBD,gDAuBC;AAED;;;;;;GAMG;AACH,MAAa,SAAS;IAGpB;;;;;;;;;;;;;;;OAeG;IACH,YAAY,QAA6C;QAlBzD,iCAAgC;QAmB9B,uBAAA,IAAI,kBAAQ,IAAI,uCAAkB,CAAC,QAAQ,CAAC,MAAA,CAAC;IAC/C,CAAC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,QAAQ;QACN,OAAO,uBAAA,IAAI,sBAAK,CAAC,QAAQ,EAAE,CAAC;IAC9B,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,UAAU,CACf,GAA0B;QAE1B,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,GAAG,CAAC,MAAc,EAAE,GAAW;QAC7B,MAAM,KAAK,GAAG,uBAAA,IAAI,sBAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,OAAO,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACtD,CAAC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,GAAG,CAAC,MAAc,EAAE,GAAW;QAC7B,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,SAAS,CAAC;IAC7C,CAAC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,MAAc,EAAE,GAAW;QAChC,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,uBAAA,IAAI,sBAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACxD,CAAC;IAED,4CAA4C;IAC5C;;;;;;;;;;;;;;;;;OAiBG;IACH,2CAA2C;IAC3C,GAAG,CAAC,GAAW,EAAE,KAAY;QAC3B,uEAAuE;QACvE,sEAAsE;QACtE,sCAAsC;QACtC,IAAI,uBAAA,IAAI,sBAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE;YACtD,MAAM,IAAI,kBAAkB,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;SACjD;QACD,uBAAA,IAAI,sBAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM;QACJ,OAAO,uBAAA,IAAI,sBAAK,CAAC,MAAM,EAAE,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACH,IAAI,IAAI;QACN,OAAO,uBAAA,IAAI,sBAAK,CAAC,IAAI,CAAC;IACxB,CAAC;CACF;AAhND,8BAgNC","sourcesContent":["import type { SnapId } from '@metamask/snaps-sdk';\n\nimport { CaseInsensitiveMap } from './CaseInsensitiveMap';\n\n/**\n * Error thrown when an invalid Snap ID is encountered.\n */\nexport class InvalidSnapIdError extends Error {\n /**\n * The ID of the Snap that caused the error.\n */\n snapId: SnapId;\n\n /**\n * The key of the element that caused the error.\n */\n key: string;\n\n /**\n * Creates an instance of `InvalidSnapIdError`.\n *\n * @param snapId - The invalid Snap ID.\n * @param key - The key associated with the invalid Snap ID.\n */\n constructor(snapId: SnapId, key: string) {\n super(`Snap \"${snapId}\" is not allowed to set \"${key}\"`);\n this.name = 'InvalidSnapIdError';\n this.snapId = snapId;\n this.key = key;\n }\n}\n\n/**\n * A map that associates a string key with a value that has a `snapId`\n * property. Note that the key is case-insensitive.\n *\n * The `snapId` property is used to ensure that only the Snap that added an\n * item to the map can modify or delete it.\n */\nexport class SnapIdMap<Value extends { snapId: SnapId }> {\n #map: CaseInsensitiveMap<Value>;\n\n /**\n * Creates a new `SnapIdMap` object.\n *\n * Example:\n *\n * ```ts\n * const items = [\n * ['foo', { snapId: '1', name: 'foo' }],\n * ['bar', { snapId: '1', name: 'bar' }],\n * ];\n * const map = new SnapIdMap(items);\n * ```\n *\n * @param iterable - An iterable object whose elements are key-value pairs.\n * Each key-value pair will be added to the new map.\n */\n constructor(iterable?: Iterable<readonly [string, Value]>) {\n this.#map = new CaseInsensitiveMap(iterable);\n }\n\n /**\n * Returns a plain object with the same key-value pairs as this map.\n *\n * Example:\n *\n * ```ts\n * const items = [\n * ['foo', { snapId: '1', name: 'foo' }],\n * ['bar', { snapId: '1', name: 'bar' }],\n * ];\n * const map = new SnapIdMap(items);\n * map.toObject();\n * // Returns\n * // {\n * // foo: { snapId: '1', name: 'foo' },\n * // bar: { snapId: '1', name: 'bar' },\n * // }\n * ```\n *\n * @returns A plain object with the same key-value pairs as this map.\n */\n toObject(): Record<string, Value> {\n return this.#map.toObject();\n }\n\n /**\n * Returns a new `SnapIdMap` object from an plain object.\n *\n * Example:\n *\n * ```ts\n * const obj = {\n * foo: { snapId: '1', name: 'foo' },\n * bar: { snapId: '1', name: 'bar' },\n * };\n * const map = SnapIdMap.fromObject(obj);\n * ```\n *\n * @param obj - A plain object whose elements will be added to the new map.\n * @returns A new `SnapIdMap` containing the elements of the given object.\n */\n static fromObject<Value extends { snapId: SnapId }>(\n obj: Record<string, Value>,\n ): SnapIdMap<Value> {\n return new SnapIdMap(Object.entries(obj));\n }\n\n /**\n * Gets a value from the map.\n *\n * If the given key is not present in the map or the Snap ID of the value is\n * different from the given Snap ID, returns `undefined`.\n *\n * Example:\n *\n * ```ts\n * const map = new SnapIdMap();\n * map.set('foo', { snapId: '1', name: 'foo' });\n * map.get('1', 'foo'); // Returns { snapId: '1', name: 'foo' }\n * map.get('2', 'foo'); // Returns `undefined`\n * map.get('1', 'bar'); // Returns `undefined`\n * ```\n *\n * @param snapId - Snap ID present in the value to get.\n * @param key - Key of the element to get.\n * @returns The value associated with the given key and Snap ID.\n */\n get(snapId: SnapId, key: string): Value | undefined {\n const value = this.#map.get(key);\n return value?.snapId === snapId ? value : undefined;\n }\n\n /**\n * Checks if a key is present in the map.\n *\n * If the given key is not present in the map or the Snap ID of the value is\n * different from the given Snap ID, returns `false`.\n *\n * Example:\n *\n * ```ts\n * const map = new SnapIdMap();\n * map.set('foo', { snapId: '1', name: 'foo' });\n * map.has('1', 'foo'); // Returns `true`\n * map.has('2', 'foo'); // Returns `false`\n * map.has('1', 'bar'); // Returns `false`\n * ```\n *\n * @param snapId - Snap ID present in the value to check.\n * @param key - Key of the element to check.\n * @returns `true` if the key is present in the map and the Snap ID of the\n * value is equal to the given Snap ID, `false` otherwise.\n */\n has(snapId: SnapId, key: string): boolean {\n return this.get(snapId, key) !== undefined;\n }\n\n /**\n * Deletes a key from the map.\n *\n * If the given key is not present in the map or the Snap IDs don't match,\n * returns `false` and does nothing.\n *\n * Example:\n *\n * ```ts\n * const map = new SnapIdMap();\n * map.set('foo', { snapId: '1', name: 'foo' });\n * map.delete('2', 'foo'); // Returns `false`\n * map.delete('1', 'bar'); // Returns `false`\n * map.delete('1', 'foo'); // Returns `true`\n * ```\n *\n * @param snapId - Snap ID present in the value to delete.\n * @param key - Key of the element to delete.\n * @returns `true` if the key was present in the map and the Snap ID of the\n * value was equal to the given Snap ID, `false` otherwise.\n */\n delete(snapId: SnapId, key: string): boolean {\n return this.has(snapId, key) && this.#map.delete(key);\n }\n\n /* eslint-disable jsdoc/check-indentation */\n /**\n * Adds or updates a key-value pair in the map.\n *\n * Note that this method has a different behavior from the `Map.set`.\n *\n * - If the given key is not already present in the map, this method adds the\n * key-value pair to the map.\n *\n * - If the given key is already present in the map and the Snap IDs match,\n * this method updates the value associated with the key.\n *\n * - However, if the given key is already present in the map but the Snap IDs\n * do not match, this method throws an error.\n *\n * @param key - Key of the element to add or update.\n * @param value - Value of the element to add or update.\n * @returns The map itself.\n */\n /* eslint-enable jsdoc/check-indentation */\n set(key: string, value: Value): this {\n // If the key is present in the map but isn't associated with the given\n // Snap ID, it means that the item was added to the map by a different\n // Snap. In this case, throw an error.\n if (this.#map.has(key) && !this.has(value.snapId, key)) {\n throw new InvalidSnapIdError(value.snapId, key);\n }\n this.#map.set(key, value);\n return this;\n }\n\n /**\n * Returns an iterable of the values in the map.\n *\n * Example:\n *\n * ```ts\n * const map = new SnapIdMap([\n * ['foo', { snapId: '1', name: 'foo' }],\n * ['bar', { snapId: '1', name: 'bar' }],\n * ]);\n * const values = [...map.values()];\n * // Returns\n * // [\n * // { snapId: '1', name: 'foo' },\n * // { snapId: '1', name: 'bar' },\n * // ]\n * ```\n *\n * @returns An iterable of the values in the map.\n */\n values(): IterableIterator<Value> {\n return this.#map.values();\n }\n\n /**\n * Returns the number of key-value pairs in the map.\n *\n * @returns The number of key-value pairs in the map.\n */\n get size(): number {\n return this.#map.size;\n }\n}\n"]}
1
+ {"version":3,"file":"SnapIdMap.js","sourceRoot":"","sources":["../src/SnapIdMap.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAEA,6DAA0D;AAE1D;;GAEG;AACH,MAAa,kBAAmB,SAAQ,KAAK;IAW3C;;;;;OAKG;IACH,YAAY,MAAc,EAAE,GAAW;QACrC,KAAK,CAAC,SAAS,MAAM,4BAA4B,GAAG,GAAG,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;CACF;AAvBD,gDAuBC;AAED;;;;;;GAMG;AACH,MAAa,SAAS;IAGpB;;;;;;;;;;;;;;;OAeG;IACH,YAAY,QAA6C;QAlBhD,iCAAgC;QAmBvC,uBAAA,IAAI,kBAAQ,IAAI,uCAAkB,CAAC,QAAQ,CAAC,MAAA,CAAC;IAC/C,CAAC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,QAAQ;QACN,OAAO,uBAAA,IAAI,sBAAK,CAAC,QAAQ,EAAE,CAAC;IAC9B,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,UAAU,CACf,GAA0B;QAE1B,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,GAAG,CAAC,MAAc,EAAE,GAAW;QAC7B,MAAM,KAAK,GAAG,uBAAA,IAAI,sBAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,OAAO,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACtD,CAAC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,GAAG,CAAC,MAAc,EAAE,GAAW;QAC7B,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,SAAS,CAAC;IAC7C,CAAC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,MAAc,EAAE,GAAW;QAChC,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,uBAAA,IAAI,sBAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACxD,CAAC;IAED,4CAA4C;IAC5C;;;;;;;;;;;;;;;;;OAiBG;IACH,2CAA2C;IAC3C,GAAG,CAAC,GAAW,EAAE,KAAY;QAC3B,uEAAuE;QACvE,sEAAsE;QACtE,sCAAsC;QACtC,IAAI,uBAAA,IAAI,sBAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;YACvD,MAAM,IAAI,kBAAkB,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAClD,CAAC;QACD,uBAAA,IAAI,sBAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM;QACJ,OAAO,uBAAA,IAAI,sBAAK,CAAC,MAAM,EAAE,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACH,IAAI,IAAI;QACN,OAAO,uBAAA,IAAI,sBAAK,CAAC,IAAI,CAAC;IACxB,CAAC;CACF;AAhND,8BAgNC","sourcesContent":["import type { SnapId } from '@metamask/snaps-sdk';\n\nimport { CaseInsensitiveMap } from './CaseInsensitiveMap';\n\n/**\n * Error thrown when an invalid Snap ID is encountered.\n */\nexport class InvalidSnapIdError extends Error {\n /**\n * The ID of the Snap that caused the error.\n */\n snapId: SnapId;\n\n /**\n * The key of the element that caused the error.\n */\n key: string;\n\n /**\n * Creates an instance of `InvalidSnapIdError`.\n *\n * @param snapId - The invalid Snap ID.\n * @param key - The key associated with the invalid Snap ID.\n */\n constructor(snapId: SnapId, key: string) {\n super(`Snap \"${snapId}\" is not allowed to set \"${key}\"`);\n this.name = 'InvalidSnapIdError';\n this.snapId = snapId;\n this.key = key;\n }\n}\n\n/**\n * A map that associates a string key with a value that has a `snapId`\n * property. Note that the key is case-insensitive.\n *\n * The `snapId` property is used to ensure that only the Snap that added an\n * item to the map can modify or delete it.\n */\nexport class SnapIdMap<Value extends { snapId: SnapId }> {\n readonly #map: CaseInsensitiveMap<Value>;\n\n /**\n * Creates a new `SnapIdMap` object.\n *\n * Example:\n *\n * ```ts\n * const items = [\n * ['foo', { snapId: '1', name: 'foo' }],\n * ['bar', { snapId: '1', name: 'bar' }],\n * ];\n * const map = new SnapIdMap(items);\n * ```\n *\n * @param iterable - An iterable object whose elements are key-value pairs.\n * Each key-value pair will be added to the new map.\n */\n constructor(iterable?: Iterable<readonly [string, Value]>) {\n this.#map = new CaseInsensitiveMap(iterable);\n }\n\n /**\n * Returns a plain object with the same key-value pairs as this map.\n *\n * Example:\n *\n * ```ts\n * const items = [\n * ['foo', { snapId: '1', name: 'foo' }],\n * ['bar', { snapId: '1', name: 'bar' }],\n * ];\n * const map = new SnapIdMap(items);\n * map.toObject();\n * // Returns\n * // {\n * // foo: { snapId: '1', name: 'foo' },\n * // bar: { snapId: '1', name: 'bar' },\n * // }\n * ```\n *\n * @returns A plain object with the same key-value pairs as this map.\n */\n toObject(): Record<string, Value> {\n return this.#map.toObject();\n }\n\n /**\n * Returns a new `SnapIdMap` object from an plain object.\n *\n * Example:\n *\n * ```ts\n * const obj = {\n * foo: { snapId: '1', name: 'foo' },\n * bar: { snapId: '1', name: 'bar' },\n * };\n * const map = SnapIdMap.fromObject(obj);\n * ```\n *\n * @param obj - A plain object whose elements will be added to the new map.\n * @returns A new `SnapIdMap` containing the elements of the given object.\n */\n static fromObject<Value extends { snapId: SnapId }>(\n obj: Record<string, Value>,\n ): SnapIdMap<Value> {\n return new SnapIdMap(Object.entries(obj));\n }\n\n /**\n * Gets a value from the map.\n *\n * If the given key is not present in the map or the Snap ID of the value is\n * different from the given Snap ID, returns `undefined`.\n *\n * Example:\n *\n * ```ts\n * const map = new SnapIdMap();\n * map.set('foo', { snapId: '1', name: 'foo' });\n * map.get('1', 'foo'); // Returns { snapId: '1', name: 'foo' }\n * map.get('2', 'foo'); // Returns `undefined`\n * map.get('1', 'bar'); // Returns `undefined`\n * ```\n *\n * @param snapId - Snap ID present in the value to get.\n * @param key - Key of the element to get.\n * @returns The value associated with the given key and Snap ID.\n */\n get(snapId: SnapId, key: string): Value | undefined {\n const value = this.#map.get(key);\n return value?.snapId === snapId ? value : undefined;\n }\n\n /**\n * Checks if a key is present in the map.\n *\n * If the given key is not present in the map or the Snap ID of the value is\n * different from the given Snap ID, returns `false`.\n *\n * Example:\n *\n * ```ts\n * const map = new SnapIdMap();\n * map.set('foo', { snapId: '1', name: 'foo' });\n * map.has('1', 'foo'); // Returns `true`\n * map.has('2', 'foo'); // Returns `false`\n * map.has('1', 'bar'); // Returns `false`\n * ```\n *\n * @param snapId - Snap ID present in the value to check.\n * @param key - Key of the element to check.\n * @returns `true` if the key is present in the map and the Snap ID of the\n * value is equal to the given Snap ID, `false` otherwise.\n */\n has(snapId: SnapId, key: string): boolean {\n return this.get(snapId, key) !== undefined;\n }\n\n /**\n * Deletes a key from the map.\n *\n * If the given key is not present in the map or the Snap IDs don't match,\n * returns `false` and does nothing.\n *\n * Example:\n *\n * ```ts\n * const map = new SnapIdMap();\n * map.set('foo', { snapId: '1', name: 'foo' });\n * map.delete('2', 'foo'); // Returns `false`\n * map.delete('1', 'bar'); // Returns `false`\n * map.delete('1', 'foo'); // Returns `true`\n * ```\n *\n * @param snapId - Snap ID present in the value to delete.\n * @param key - Key of the element to delete.\n * @returns `true` if the key was present in the map and the Snap ID of the\n * value was equal to the given Snap ID, `false` otherwise.\n */\n delete(snapId: SnapId, key: string): boolean {\n return this.has(snapId, key) && this.#map.delete(key);\n }\n\n /* eslint-disable jsdoc/check-indentation */\n /**\n * Adds or updates a key-value pair in the map.\n *\n * Note that this method has a different behavior from the `Map.set`.\n *\n * - If the given key is not already present in the map, this method adds the\n * key-value pair to the map.\n *\n * - If the given key is already present in the map and the Snap IDs match,\n * this method updates the value associated with the key.\n *\n * - However, if the given key is already present in the map but the Snap IDs\n * do not match, this method throws an error.\n *\n * @param key - Key of the element to add or update.\n * @param value - Value of the element to add or update.\n * @returns The map itself.\n */\n /* eslint-enable jsdoc/check-indentation */\n set(key: string, value: Value): this {\n // If the key is present in the map but isn't associated with the given\n // Snap ID, it means that the item was added to the map by a different\n // Snap. In this case, throw an error.\n if (this.#map.has(key) && !this.has(value.snapId, key)) {\n throw new InvalidSnapIdError(value.snapId, key);\n }\n this.#map.set(key, value);\n return this;\n }\n\n /**\n * Returns an iterable of the values in the map.\n *\n * Example:\n *\n * ```ts\n * const map = new SnapIdMap([\n * ['foo', { snapId: '1', name: 'foo' }],\n * ['bar', { snapId: '1', name: 'bar' }],\n * ]);\n * const values = [...map.values()];\n * // Returns\n * // [\n * // { snapId: '1', name: 'foo' },\n * // { snapId: '1', name: 'bar' },\n * // ]\n * ```\n *\n * @returns An iterable of the values in the map.\n */\n values(): IterableIterator<Value> {\n return this.#map.values();\n }\n\n /**\n * Returns the number of key-value pairs in the map.\n *\n * @returns The number of key-value pairs in the map.\n */\n get size(): number {\n return this.#map.size;\n }\n}\n"]}
@@ -15,7 +15,7 @@ export declare const SNAP_KEYRING_TYPE = "Snap Keyring";
15
15
  * This state is persisted by the keyring controller and passed to the Snap
16
16
  * keyring when it's created.
17
17
  */
18
- export declare type KeyringState = {
18
+ export type KeyringState = {
19
19
  accounts: Record<string, {
20
20
  account: KeyringAccount;
21
21
  snapId: SnapId;
@@ -26,7 +26,7 @@ export declare type KeyringState = {
26
26
  *
27
27
  * These callbacks are used to interact with other components.
28
28
  */
29
- export declare type SnapKeyringCallbacks = {
29
+ export type SnapKeyringCallbacks = {
30
30
  saveState: () => Promise<void>;
31
31
  addressExists(address: string): Promise<boolean>;
32
32
  addAccount(address: string, snapId: SnapId, handleUserInput: (accepted: boolean) => Promise<void>, accountNameSuggestion?: string, displayConfirmation?: boolean): Promise<void>;
@@ -87,6 +87,7 @@ export declare class SnapKeyring extends EventEmitter {
87
87
  * @param address - Sender's address.
88
88
  * @param transaction - Transaction.
89
89
  * @param _opts - Transaction options (not used).
90
+ * @returns A promise that resolves to the signed transaction.
90
91
  */
91
92
  signTransaction(address: string, transaction: TypedTransaction, _opts?: {}): Promise<Json | TypedTransaction>;
92
93
  /**
@@ -1,4 +1,7 @@
1
1
  "use strict";
2
+ /* eslint-disable @typescript-eslint/no-redundant-type-constituents */
3
+ // This rule seems to be triggering a false positive. Possibly eslint is not
4
+ // inferring the EthMethod, BtcMethod, and InternalAccount types correctly.
2
5
  var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
6
  if (kind === "m") throw new TypeError("Private method is not writable");
4
7
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
@@ -10,7 +13,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
13
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
14
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
15
  };
13
- var _SnapKeyring_instances, _SnapKeyring_snapClient, _SnapKeyring_accounts, _SnapKeyring_requests, _SnapKeyring_callbacks, _SnapKeyring_handleAccountCreated, _SnapKeyring_handleAccountUpdated, _SnapKeyring_handleAccountDeleted, _SnapKeyring_handleRequestApproved, _SnapKeyring_handleRequestRejected, _SnapKeyring_submitRequest, _SnapKeyring_hasMethod, _SnapKeyring_createRequestPromise, _SnapKeyring_submitSnapRequest, _SnapKeyring_handleSyncResponse, _SnapKeyring_handleAsyncResponse, _SnapKeyring_validateRedirectUrl, _SnapKeyring_resolveAddress, _SnapKeyring_getSnapMetadata, _SnapKeyring_getSnapAllowedOrigins;
16
+ var _SnapKeyring_instances, _SnapKeyring_snapClient, _SnapKeyring_accounts, _SnapKeyring_requests, _SnapKeyring_callbacks, _SnapKeyring_handleAccountCreated, _SnapKeyring_handleAccountUpdated, _SnapKeyring_handleAccountDeleted, _SnapKeyring_handleRequestApproved, _SnapKeyring_handleRequestRejected, _SnapKeyring_submitRequest, _SnapKeyring_hasMethod, _SnapKeyring_createRequestPromise, _SnapKeyring_submitSnapRequest, _SnapKeyring_handleSyncResponse, _SnapKeyring_handleAsyncResponse, _SnapKeyring_sanitizeRedirectUrl, _SnapKeyring_validateRedirectUrl, _SnapKeyring_resolveAddress, _SnapKeyring_getSnapMetadata, _SnapKeyring_getSnapAllowedOrigins;
14
17
  Object.defineProperty(exports, "__esModule", { value: true });
15
18
  exports.SnapKeyring = exports.SNAP_KEYRING_TYPE = void 0;
16
19
  const tx_1 = require("@ethereumjs/tx");
@@ -74,19 +77,19 @@ class SnapKeyring extends events_1.EventEmitter {
74
77
  async handleKeyringSnapMessage(snapId, message) {
75
78
  (0, superstruct_1.assert)(message, types_1.SnapMessageStruct);
76
79
  switch (message.method) {
77
- case keyring_api_1.KeyringEvent.AccountCreated: {
80
+ case `${keyring_api_1.KeyringEvent.AccountCreated}`: {
78
81
  return __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_handleAccountCreated).call(this, snapId, message);
79
82
  }
80
- case keyring_api_1.KeyringEvent.AccountUpdated: {
83
+ case `${keyring_api_1.KeyringEvent.AccountUpdated}`: {
81
84
  return __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_handleAccountUpdated).call(this, snapId, message);
82
85
  }
83
- case keyring_api_1.KeyringEvent.AccountDeleted: {
86
+ case `${keyring_api_1.KeyringEvent.AccountDeleted}`: {
84
87
  return __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_handleAccountDeleted).call(this, snapId, message);
85
88
  }
86
- case keyring_api_1.KeyringEvent.RequestApproved: {
89
+ case `${keyring_api_1.KeyringEvent.RequestApproved}`: {
87
90
  return __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_handleRequestApproved).call(this, snapId, message);
88
91
  }
89
- case keyring_api_1.KeyringEvent.RequestRejected: {
92
+ case `${keyring_api_1.KeyringEvent.RequestRejected}`: {
90
93
  return __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_handleRequestRejected).call(this, snapId, message);
91
94
  }
92
95
  default:
@@ -141,6 +144,7 @@ class SnapKeyring extends events_1.EventEmitter {
141
144
  * @param address - Sender's address.
142
145
  * @param transaction - Transaction.
143
146
  * @param _opts - Transaction options (not used).
147
+ * @returns A promise that resolves to the signed transaction.
144
148
  */
145
149
  async signTransaction(address, transaction, _opts = {}) {
146
150
  const chainId = transaction.common.chainId();
@@ -245,7 +249,7 @@ class SnapKeyring extends events_1.EventEmitter {
245
249
  address,
246
250
  method: keyring_api_1.EthMethod.PrepareUserOperation,
247
251
  params: (0, util_1.toJson)(transactions),
248
- expectSync: true,
252
+ noPending: true,
249
253
  // We assume the chain ID is already well formatted
250
254
  chainId: (0, utils_1.toCaipChainId)(utils_1.KnownCaipNamespace.Eip155, context.chainId),
251
255
  }), keyring_api_1.EthBaseUserOperationStruct);
@@ -264,7 +268,7 @@ class SnapKeyring extends events_1.EventEmitter {
264
268
  address,
265
269
  method: keyring_api_1.EthMethod.PatchUserOperation,
266
270
  params: (0, util_1.toJson)([userOp]),
267
- expectSync: true,
271
+ noPending: true,
268
272
  // We assume the chain ID is already well formatted
269
273
  chainId: (0, utils_1.toCaipChainId)(utils_1.KnownCaipNamespace.Eip155, context.chainId),
270
274
  }), keyring_api_1.EthUserOperationPatchStruct);
@@ -479,10 +483,10 @@ async function _SnapKeyring_handleRequestRejected(snapId, message) {
479
483
  * @param opts.method - Method to call.
480
484
  * @param opts.params - Method parameters.
481
485
  * @param opts.chainId - Selected chain ID (CAIP-2).
482
- * @param opts.expectSync - Whether the request should be synchronous.
486
+ * @param opts.noPending - Whether the response is allowed to be pending.
483
487
  * @returns Promise that resolves to the result of the method call.
484
488
  */
485
- async function _SnapKeyring_submitRequest({ address, method, params, chainId = '', expectSync = false, }) {
489
+ async function _SnapKeyring_submitRequest({ address, method, params, chainId = '', noPending = false, }) {
486
490
  const { account, snapId } = __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_resolveAddress).call(this, address);
487
491
  if (!__classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_hasMethod).call(this, account, method)) {
488
492
  throw new Error(`Method '${method}' not supported for account ${account.address}`);
@@ -502,8 +506,8 @@ async function _SnapKeyring_submitRequest({ address, method, params, chainId = '
502
506
  // Some methods, like the ones used to prepare and patch user operations,
503
507
  // require the Snap to answer synchronously in order to work with the
504
508
  // confirmation flow. This check lets the caller enforce this behavior.
505
- if (expectSync && response.pending) {
506
- throw new Error(`Request '${requestId}' to snap '${snapId}' is pending and expectSync is true.`);
509
+ if (noPending && response.pending) {
510
+ throw new Error(`Request '${requestId}' to snap '${snapId}' is pending and noPending is true.`);
507
511
  }
508
512
  // If the Snap answers synchronously, the promise must be removed from the
509
513
  // map to prevent a leak.
@@ -569,11 +573,15 @@ async function _SnapKeyring_submitSnapRequest({ snapId, requestId, account, meth
569
573
  * @throws An error if the redirect URL is not an allowed origin for the Snap.
570
574
  */
571
575
  async function _SnapKeyring_handleAsyncResponse(redirect, snapId) {
572
- const { message = '', url = '' } = redirect;
576
+ const { message = '', url: redirectUrl = '' } = redirect;
577
+ const url = __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_sanitizeRedirectUrl).call(this, redirectUrl);
573
578
  if (url) {
574
579
  __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_validateRedirectUrl).call(this, url, snapId);
575
580
  }
576
581
  await __classPrivateFieldGet(this, _SnapKeyring_callbacks, "f").redirectUser(snapId, url, message);
582
+ }, _SnapKeyring_sanitizeRedirectUrl = function _SnapKeyring_sanitizeRedirectUrl(url) {
583
+ // We do check if the URL is empty or not since the Snap might not returns any URL at all.
584
+ return url ? (0, util_1.sanitizeUrl)(url) : url;
577
585
  }, _SnapKeyring_validateRedirectUrl = function _SnapKeyring_validateRedirectUrl(url, snapId) {
578
586
  const { origin } = new URL(url);
579
587
  const snap = __classPrivateFieldGet(this, _SnapKeyring_snapClient, "f").getController().get(snapId);
@@ -1 +1 @@
1
- {"version":3,"file":"SnapKeyring.js","sourceRoot":"","sources":["../src/SnapKeyring.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AACA,uCAAoD;AAEpD,yDAA8D;AAY9D,uDAW+B;AAI/B,uDAAqE;AAErE,2CAIyB;AACzB,mCAAsC;AACtC,+BAAkC;AAElC,uDAAoD;AACpD,+EAA4E;AAC5E,qCAAgD;AAChD,2CAAwC;AAExC,mCAA4C;AAC5C,iCAMgB;AAEH,QAAA,iBAAiB,GAAG,cAAc,CAAC;AA2ChD;;GAEG;AACH,MAAa,WAAY,SAAQ,qBAAY;IAgC3C;;;;;;OAMG;IACH,YAAY,UAA0B,EAAE,SAA+B;QACrE,KAAK,EAAE,CAAC;;QAnCV;;WAEG;QACH,0CAAyC;QAEzC;;;WAGG;QACH,wCAGG;QAEH;;WAEG;QACH,wCAGG;QAEH;;WAEG;QACH,yCAAiC;QAW/B,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC;QAC7B,uBAAA,IAAI,2BAAe,IAAI,yDAA2B,CAAC,EAAE,UAAU,EAAE,CAAC,MAAA,CAAC;QACnE,uBAAA,IAAI,yBAAa,IAAI,qBAAS,EAAE,MAAA,CAAC;QACjC,uBAAA,IAAI,yBAAa,IAAI,qBAAS,EAAE,MAAA,CAAC;QACjC,uBAAA,IAAI,0BAAc,SAAS,MAAA,CAAC;IAC9B,CAAC;IA8JD;;;;;;OAMG;IACH,KAAK,CAAC,wBAAwB,CAC5B,MAAc,EACd,OAAoB;QAEpB,IAAA,oBAAM,EAAC,OAAO,EAAE,yBAAiB,CAAC,CAAC;QACnC,QAAQ,OAAO,CAAC,MAAM,EAAE;YACtB,KAAK,0BAAY,CAAC,cAAc,CAAC,CAAC;gBAChC,OAAO,uBAAA,IAAI,iEAAsB,MAA1B,IAAI,EAAuB,MAAM,EAAE,OAAO,CAAC,CAAC;aACpD;YAED,KAAK,0BAAY,CAAC,cAAc,CAAC,CAAC;gBAChC,OAAO,uBAAA,IAAI,iEAAsB,MAA1B,IAAI,EAAuB,MAAM,EAAE,OAAO,CAAC,CAAC;aACpD;YAED,KAAK,0BAAY,CAAC,cAAc,CAAC,CAAC;gBAChC,OAAO,uBAAA,IAAI,iEAAsB,MAA1B,IAAI,EAAuB,MAAM,EAAE,OAAO,CAAC,CAAC;aACpD;YAED,KAAK,0BAAY,CAAC,eAAe,CAAC,CAAC;gBACjC,OAAO,uBAAA,IAAI,kEAAuB,MAA3B,IAAI,EAAwB,MAAM,EAAE,OAAO,CAAC,CAAC;aACrD;YAED,KAAK,0BAAY,CAAC,eAAe,CAAC,CAAC;gBACjC,OAAO,uBAAA,IAAI,kEAAuB,MAA3B,IAAI,EAAwB,MAAM,EAAE,OAAO,CAAC,CAAC;aACrD;YAED;gBACE,MAAM,IAAI,KAAK,CAAC,yBAAyB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;SAC9D;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,SAAS;QACb,OAAO;YACL,QAAQ,EAAE,uBAAA,IAAI,6BAAU,CAAC,QAAQ,EAAE;SACpC,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,WAAW,CAAC,KAA+B;QAC/C,wEAAwE;QACxE,6BAA6B;QAC7B,IAAI,KAAK,KAAK,SAAS,EAAE;YACvB,OAAO;SACR;QACD,uBAAA,IAAI,yBAAa,qBAAS,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAA,CAAC;IACxD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,WAAW;QACf,OAAO,IAAA,aAAM,EACX,CAAC,GAAG,uBAAA,IAAI,6BAAU,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAC/C,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAC9B,CACF,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,mBAAmB,CAAC,MAAc;QACtC,OAAO,IAAA,aAAM,EACX,CAAC,GAAG,uBAAA,IAAI,6BAAU,CAAC,MAAM,EAAE,CAAC;aACzB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,aAAa,KAAK,MAAM,CAAC;aAC/D,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CACvD,CAAC;IACJ,CAAC;IAiND;;;;;;OAMG;IACH,KAAK,CAAC,eAAe,CACnB,OAAe,EACf,WAA6B,EAC7B,KAAK,GAAG,EAAE;QAEV,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAC7C,MAAM,EAAE,GAAG,IAAA,aAAM,EAAC;YAChB,GAAG,WAAW,CAAC,MAAM,EAAE;YACvB,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,KAAK,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE;YAC1C,OAAO,EAAE,IAAA,mBAAW,EAAC,OAAO,CAAC;SAC9B,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,MAAM,uBAAA,IAAI,0DAAe,MAAnB,IAAI,EAAgB;YACzC,OAAO;YACP,MAAM,EAAE,uBAAS,CAAC,eAAe;YACjC,MAAM,EAAE,CAAC,EAAE,CAAC;YACZ,OAAO,EAAE,IAAA,qBAAa,EAAC,0BAAkB,CAAC,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC;SAChE,CAAC,CAAC;QAEH,yEAAyE;QACzE,0CAA0C;QAC1C,MAAM,SAAS,GAAG,IAAA,kBAAI,EACpB,QAAQ,EACR,IAAA,oBAAM,EAAC;YACL,CAAC,EAAE,IAAA,oBAAM,GAAE;YACX,CAAC,EAAE,IAAA,oBAAM,GAAE;YACX,CAAC,EAAE,IAAA,oBAAM,GAAE;SACZ,CAAC,CACH,CAAC;QAEF,OAAO,uBAAkB,CAAC,UAAU,CAAC;YACnC,GAAI,EAA2B;YAC/B,CAAC,EAAE,SAAS,CAAC,CAAC;YACd,CAAC,EAAE,SAAS,CAAC,CAAC;YACd,CAAC,EAAE,SAAS,CAAC,CAAC;SACf,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,aAAa,CACjB,OAAe,EACf,IAAiE,EACjE,IAAI,GAAG,EAAE,OAAO,EAAE,mCAAoB,CAAC,EAAE,EAAE;QAE3C,MAAM,OAAO,GAAG;YACd,CAAC,mCAAoB,CAAC,EAAE,CAAC,EAAE,uBAAS,CAAC,eAAe;YACpD,CAAC,mCAAoB,CAAC,EAAE,CAAC,EAAE,uBAAS,CAAC,eAAe;YACpD,CAAC,mCAAoB,CAAC,EAAE,CAAC,EAAE,uBAAS,CAAC,eAAe;SACrD,CAAC;QAEF,yEAAyE;QACzE,yDAAyD;QACzD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,uBAAS,CAAC,eAAe,CAAC;QAElE,4EAA4E;QAC5E,iEAAiE;QACjE,MAAM,OAAO,GAAI,IAA0B,CAAC,MAAM,EAAE,OAAO,CAAC;QAE5D,OAAO,IAAA,iBAAU,EACf,MAAM,uBAAA,IAAI,0DAAe,MAAnB,IAAI,EAAgB;YACxB,OAAO;YACP,MAAM;YACN,MAAM,EAAE,IAAA,aAAM,EAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACvC,GAAG,CAAC,OAAO,KAAK,SAAS;gBACvB,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC;oBACE,OAAO,EAAE,IAAA,qBAAa,EAAC,0BAAkB,CAAC,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC;iBAChE,CAAC;SACP,CAAC,EACF,4BAAc,CACf,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,IAAS;QAC1C,OAAO,IAAA,iBAAU,EACf,MAAM,uBAAA,IAAI,0DAAe,MAAnB,IAAI,EAAgB;YACxB,OAAO;YACP,MAAM,EAAE,uBAAS,CAAC,IAAI;YACtB,MAAM,EAAE,IAAA,aAAM,EAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;SACxC,CAAC,EACF,4BAAc,CACf,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,mBAAmB,CAAC,OAAe,EAAE,IAAS;QAClD,OAAO,IAAA,iBAAU,EACf,MAAM,uBAAA,IAAI,0DAAe,MAAnB,IAAI,EAAgB;YACxB,OAAO;YACP,MAAM,EAAE,uBAAS,CAAC,YAAY;YAC9B,MAAM,EAAE,IAAA,aAAM,EAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;SACxC,CAAC,EACF,4BAAc,CACf,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,oBAAoB,CACxB,OAAe,EACf,YAAkC,EAClC,OAAgC;QAEhC,OAAO,IAAA,iBAAU,EACf,MAAM,uBAAA,IAAI,0DAAe,MAAnB,IAAI,EAAgB;YACxB,OAAO;YACP,MAAM,EAAE,uBAAS,CAAC,oBAAoB;YACtC,MAAM,EAAE,IAAA,aAAM,EAAS,YAAY,CAAC;YACpC,UAAU,EAAE,IAAI;YAChB,mDAAmD;YACnD,OAAO,EAAE,IAAA,qBAAa,EAAC,0BAAkB,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC;SACnE,CAAC,EACF,wCAA0B,CAC3B,CAAC;IACJ,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,kBAAkB,CACtB,OAAe,EACf,MAAwB,EACxB,OAAgC;QAEhC,OAAO,IAAA,iBAAU,EACf,MAAM,uBAAA,IAAI,0DAAe,MAAnB,IAAI,EAAgB;YACxB,OAAO;YACP,MAAM,EAAE,uBAAS,CAAC,kBAAkB;YACpC,MAAM,EAAE,IAAA,aAAM,EAAS,CAAC,MAAM,CAAC,CAAC;YAChC,UAAU,EAAE,IAAI;YAChB,mDAAmD;YACnD,OAAO,EAAE,IAAA,qBAAa,EAAC,0BAAkB,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC;SACnE,CAAC,EACF,yCAA2B,CAC5B,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,iBAAiB,CACrB,OAAe,EACf,MAAwB,EACxB,OAAgC;QAEhC,OAAO,IAAA,iBAAU,EACf,MAAM,uBAAA,IAAI,0DAAe,MAAnB,IAAI,EAAgB;YACxB,OAAO;YACP,MAAM,EAAE,uBAAS,CAAC,iBAAiB;YACnC,MAAM,EAAE,IAAA,aAAM,EAAS,CAAC,MAAM,CAAC,CAAC;YAChC,mDAAmD;YACnD,OAAO,EAAE,IAAA,qBAAa,EAAC,0BAAkB,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC;SACnE,CAAC,EACF,4BAAc,CACf,CAAC;IACJ,CAAC;IAED;;;;;;;;;;OAUG;IACH,aAAa,CAAC,QAAgB;QAC5B,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,aAAa,CAAC,OAAe;QACjC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,uBAAA,IAAI,2DAAgB,MAApB,IAAI,EAAiB,OAAO,CAAC,CAAC;QAE1D,wEAAwE;QACxE,qBAAqB;QACrB,uBAAA,IAAI,6BAAU,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QAE1C,IAAI;YACF,MAAM,uBAAA,IAAI,+BAAY,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;SACrE;QAAC,OAAO,KAAK,EAAE;YACd,uEAAuE;YACvE,wEAAwE;YACxE,WAAW;YACX,OAAO,CAAC,KAAK,CACX,YAAY,OAAO,0CAA0C,MAAM,IAAI,EACvE,KAAK,CACN,CAAC;SACH;IACH,CAAC;IAgDD;;;;;OAKG;IACH,mBAAmB,CAAC,OAAe;QACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACrC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE,CACnD,IAAA,uBAAgB,EAAC,cAAc,EAAE,OAAO,CAAC,CAC1C,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,YAAY;QACV,OAAO,CAAC,GAAG,uBAAA,IAAI,6BAAU,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE;YAC9D,MAAM,IAAI,GAAG,uBAAA,IAAI,4DAAiB,MAArB,IAAI,EAAkB,MAAM,CAAC,CAAC;YAC3C,OAAO;gBACL,GAAG,OAAO;gBACV,iDAAiD;gBACjD,EAAE;gBACF,mEAAmE;gBACnE,qEAAqE;gBACrE,uEAAuE;gBACvE,WAAW;gBACX,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE;gBACtC,QAAQ,EAAE;oBACR,IAAI,EAAE,EAAE;oBACR,UAAU,EAAE,CAAC;oBACb,OAAO,EAAE;wBACP,IAAI,EAAE,IAAI,CAAC,IAAI;qBAChB;oBACD,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC;iBACpC;aACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;;AAh0BH,kCAi0BC;;AAjxBC;;;;;;GAMG;AACH,KAAK,4CACH,MAAc,EACd,OAAoB;IAEpB,IAAA,oBAAM,EAAC,OAAO,EAAE,uCAAyB,CAAC,CAAC;IAC3C,MAAM,EAAE,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,GAC3D,OAAO,CAAC,MAAM,CAAC;IAEjB,yEAAyE;IACzE,0EAA0E;IAC1E,0BAA0B;IAC1B,IAAI,MAAM,uBAAA,IAAI,8BAAW,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE;QACtE,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,CAAC,OAAO,kBAAkB,CAAC,CAAC;KACxE;IAED,0EAA0E;IAC1E,wDAAwD;IACxD,IAAI,uBAAA,IAAI,6BAAU,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE;QAC1C,MAAM,IAAI,KAAK,CAAC,YAAY,OAAO,CAAC,EAAE,kBAAkB,CAAC,CAAC;KAC3D;IAED,MAAM,uBAAA,IAAI,8BAAW,CAAC,UAAU,CAC9B,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,EAC7B,MAAM,EACN,KAAK,EAAE,QAAiB,EAAE,EAAE;QAC1B,IAAI,QAAQ,EAAE;YACZ,uBAAA,IAAI,6BAAU,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YACpD,MAAM,uBAAA,IAAI,8BAAW,CAAC,SAAS,EAAE,CAAC;SACnC;IACH,CAAC,EACD,qBAAqB,EACrB,mBAAmB,CACpB,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,KAAK,4CACH,MAAc,EACd,OAAoB;IAEpB,IAAA,oBAAM,EAAC,OAAO,EAAE,uCAAyB,CAAC,CAAC;IAC3C,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAC/C,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAC3B,uBAAA,IAAI,6BAAU,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC;QACzC,IAAA,iBAAU,EAAC,YAAY,UAAU,CAAC,EAAE,aAAa,CAAC,CAAC;IAErD,uEAAuE;IACvE,0EAA0E;IAC1E,6BAA6B;IAC7B,IAAI,CAAC,IAAA,uBAAgB,EAAC,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE;QAC7D,MAAM,IAAI,KAAK,CAAC,qCAAqC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;KACxE;IAED,uBAAA,IAAI,6BAAU,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC;IACnE,MAAM,uBAAA,IAAI,8BAAW,CAAC,SAAS,EAAE,CAAC;IAClC,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,KAAK,4CACH,MAAc,EACd,OAAoB;IAEpB,IAAA,oBAAM,EAAC,OAAO,EAAE,uCAAyB,CAAC,CAAC;IAC3C,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAC9B,MAAM,KAAK,GAAG,uBAAA,IAAI,6BAAU,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAE7C,wEAAwE;IACxE,2CAA2C;IAC3C,EAAE;IACF,yEAAyE;IACzE,kEAAkE;IAClE,IAAI,KAAK,KAAK,SAAS,EAAE;QACvB,OAAO,IAAI,CAAC;KACb;IAED,kEAAkE;IAClE,kBAAkB;IAClB,MAAM,EACJ,OAAO,EAAE,EAAE,OAAO,EAAE,GACrB,GAAG,KAAK,CAAC;IAEV,MAAM,uBAAA,IAAI,8BAAW,CAAC,aAAa,CACjC,OAAO,CAAC,WAAW,EAAE,EACrB,MAAM,EACN,KAAK,EAAE,QAAQ,EAAE,EAAE;QACjB,IAAI,QAAQ,EAAE;YACZ,MAAM,uBAAA,IAAI,8BAAW,CAAC,SAAS,EAAE,CAAC;SACnC;IACH,CAAC,CACF,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,KAAK,6CACH,MAAc,EACd,OAAoB;IAEpB,IAAA,oBAAM,EAAC,OAAO,EAAE,wCAA0B,CAAC,CAAC;IAC5C,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IACtC,MAAM,EAAE,OAAO,EAAE,GACf,uBAAA,IAAI,6BAAU,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,IAAA,iBAAU,EAAC,YAAY,EAAE,aAAa,CAAC,CAAC;IAE5E,uBAAA,IAAI,6BAAU,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAClC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACxB,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,KAAK,6CACH,MAAc,EACd,OAAoB;IAEpB,IAAA,oBAAM,EAAC,OAAO,EAAE,wCAA0B,CAAC,CAAC;IAC5C,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAC9B,MAAM,EAAE,OAAO,EAAE,GACf,uBAAA,IAAI,6BAAU,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,IAAA,iBAAU,EAAC,YAAY,EAAE,aAAa,CAAC,CAAC;IAE5E,uBAAA,IAAI,6BAAU,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAClC,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAC;IAC/D,OAAO,IAAI,CAAC;AACd,CAAC;AA4FD;;;;;;;;;;GAUG;AACH,KAAK,qCAAuC,EAC1C,OAAO,EACP,MAAM,EACN,MAAM,EACN,OAAO,GAAG,EAAE,EACZ,UAAU,GAAG,KAAK,GAOnB;IACC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,uBAAA,IAAI,2DAAgB,MAApB,IAAI,EAAiB,OAAO,CAAC,CAAC;IAC1D,IAAI,CAAC,uBAAA,IAAI,sDAAW,MAAf,IAAI,EAAY,OAAO,EAAE,MAAuB,CAAC,EAAE;QACtD,MAAM,IAAI,KAAK,CACb,WAAW,MAAM,+BAA+B,OAAO,CAAC,OAAO,EAAE,CAClE,CAAC;KACH;IAED,MAAM,SAAS,GAAG,IAAA,SAAI,GAAE,CAAC;IAEzB,yEAAyE;IACzE,gEAAgE;IAChE,MAAM,OAAO,GAAG,uBAAA,IAAI,iEAAsB,MAA1B,IAAI,EAAiC,SAAS,EAAE,MAAM,CAAC,CAAC;IAExE,MAAM,QAAQ,GAAG,MAAM,uBAAA,IAAI,8DAAmB,MAAvB,IAAI,EAAoB;QAC7C,MAAM;QACN,SAAS;QACT,OAAO;QACP,MAAM,EAAE,MAAuB;QAC/B,MAAM;QACN,OAAO;KACR,CAAC,CAAC;IAEH,yEAAyE;IACzE,qEAAqE;IACrE,uEAAuE;IACvE,IAAI,UAAU,IAAI,QAAQ,CAAC,OAAO,EAAE;QAClC,MAAM,IAAI,KAAK,CACb,YAAY,SAAS,cAAc,MAAM,sCAAsC,CAChF,CAAC;KACH;IAED,0EAA0E;IAC1E,yBAAyB;IACzB,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE;QACrB,OAAO,uBAAA,IAAI,+DAAoB,MAAxB,IAAI,EAAqB,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;KAC9D;IAED,8EAA8E;IAC9E,IAAI,QAAQ,CAAC,QAAQ,EAAE,OAAO,IAAI,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;QACxD,MAAM,uBAAA,IAAI,gEAAqB,MAAzB,IAAI,EAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;KAC5D;IAED,OAAO,OAAO,CAAC,OAAO,CAAC;AACzB,CAAC,2DASU,OAAuB,EAAE,MAAqB;IACvD,OAAQ,OAAO,CAAC,OAA2B,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC/D,CAAC,iFAUC,SAAiB,EACjB,MAAc;IAEd,MAAM,OAAO,GAAG,IAAI,iCAAe,EAAY,CAAC;IAChD,uBAAA,IAAI,6BAAU,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IACnD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,KAAK,yCAAoB,EACvB,MAAM,EACN,SAAS,EACT,OAAO,EACP,MAAM,EACN,MAAM,EACN,OAAO,GAQR;IACC,IAAI;QACF,MAAM,OAAO,GAAG;YACd,EAAE,EAAE,SAAS;YACb,KAAK,EAAE,OAAO;YACd,OAAO,EAAE,OAAO,CAAC,EAAE;YACnB,OAAO,EAAE;gBACP,MAAM;gBACN,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,EAAE,MAAM,EAAE,CAAC;aACxC;SACF,CAAC;QAEF,IAAA,sBAAG,EAAC,uBAAuB,EAAE,OAAO,CAAC,CAAC;QAEtC,OAAO,MAAM,uBAAA,IAAI,+BAAY,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;KACzE;IAAC,OAAO,KAAK,EAAE;QACd,IAAA,sBAAG,EAAC,uBAAuB,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAE5C,uEAAuE;QACvE,uBAAA,IAAI,6BAAU,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACzC,MAAM,KAAK,CAAC;KACb;AACH,CAAC,6EAaC,QAA0C,EAC1C,SAAiB,EACjB,MAAc;IAEd,uBAAA,IAAI,6BAAU,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACzC,OAAO,QAAQ,CAAC,MAAM,CAAC;AACzB,CAAC;AAED;;;;;;;;GAQG;AACH,KAAK,2CACH,QAA4C,EAC5C,MAAc;IAEd,MAAM,EAAE,OAAO,GAAG,EAAE,EAAE,GAAG,GAAG,EAAE,EAAE,GAAG,QAAQ,CAAC;IAC5C,IAAI,GAAG,EAAE;QACP,uBAAA,IAAI,gEAAqB,MAAzB,IAAI,EAAsB,GAAG,EAAE,MAAM,CAAC,CAAC;KACxC;IACD,MAAM,uBAAA,IAAI,8BAAW,CAAC,YAAY,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;AAC3D,CAAC,+EASoB,GAAW,EAAE,MAAc;IAC9C,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,uBAAA,IAAI,+BAAY,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1D,IAAI,CAAC,IAAI,EAAE;QACT,MAAM,IAAI,KAAK,CAAC,SAAS,MAAM,cAAc,CAAC,CAAC;KAChD;IACD,MAAM,cAAc,GAAG,uBAAA,IAAI,kEAAuB,MAA3B,IAAI,EAAwB,IAAI,CAAC,CAAC;IACzD,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;QACpC,MAAM,IAAI,KAAK,CACb,wBAAwB,MAAM,uCAAuC,MAAM,GAAG,CAC/E,CAAC;KACH;AACH,CAAC,qEA8Pe,OAAe;IAI7B,OAAO,CACL,CAAC,GAAG,uBAAA,IAAI,6BAAU,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAChD,IAAA,uBAAgB,EAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAC3C,IAAI,IAAA,iBAAU,EAAC,YAAY,OAAO,aAAa,CAAC,CAClD,CAAC;AACJ,CAAC,uEASC,MAAc;IAEd,MAAM,IAAI,GAAG,uBAAA,IAAI,+BAAY,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1D,OAAO,IAAI;QACT,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE;QACzE,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC,mFAQsB,IAAU;IAC/B,OAAO,CACL,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,EAAE,cAAc;QACrE,EAAE,CACH,CAAC;AACJ,CAAC;AArxBM,gBAAI,GAAW,yBAAiB,CAAC","sourcesContent":["import type { TypedTransaction } from '@ethereumjs/tx';\nimport { TransactionFactory } from '@ethereumjs/tx';\nimport type { TypedDataV1, TypedMessage } from '@metamask/eth-sig-util';\nimport { SignTypedDataVersion } from '@metamask/eth-sig-util';\nimport type {\n BtcMethod,\n EthBaseTransaction,\n EthBaseUserOperation,\n EthUserOperation,\n EthUserOperationPatch,\n InternalAccount,\n KeyringAccount,\n KeyringExecutionContext,\n KeyringResponse,\n} from '@metamask/keyring-api';\nimport {\n AccountCreatedEventStruct,\n AccountDeletedEventStruct,\n AccountUpdatedEventStruct,\n EthBaseUserOperationStruct,\n EthBytesStruct,\n EthMethod,\n EthUserOperationPatchStruct,\n KeyringEvent,\n RequestApprovedEventStruct,\n RequestRejectedEventStruct,\n} from '@metamask/keyring-api';\nimport type { SnapController } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport type { Snap } from '@metamask/snaps-utils';\nimport { assert, mask, object, string } from '@metamask/superstruct';\nimport type { Json } from '@metamask/utils';\nimport {\n bigIntToHex,\n KnownCaipNamespace,\n toCaipChainId,\n} from '@metamask/utils';\nimport { EventEmitter } from 'events';\nimport { v4 as uuid } from 'uuid';\n\nimport { DeferredPromise } from './DeferredPromise';\nimport { KeyringSnapControllerClient } from './KeyringSnapControllerClient';\nimport { projectLogger as log } from './logger';\nimport { SnapIdMap } from './SnapIdMap';\nimport type { SnapMessage } from './types';\nimport { SnapMessageStruct } from './types';\nimport {\n equalsIgnoreCase,\n strictMask,\n throwError,\n toJson,\n unique,\n} from './util';\n\nexport const SNAP_KEYRING_TYPE = 'Snap Keyring';\n\n// TODO: to be removed when this is added to the keyring-api\n\ntype AccountMethod = EthMethod | BtcMethod;\n\n/**\n * Snap keyring state.\n *\n * This state is persisted by the keyring controller and passed to the Snap\n * keyring when it's created.\n */\nexport type KeyringState = {\n accounts: Record<string, { account: KeyringAccount; snapId: SnapId }>;\n};\n\n/**\n * Snap keyring callbacks.\n *\n * These callbacks are used to interact with other components.\n */\nexport type SnapKeyringCallbacks = {\n saveState: () => Promise<void>;\n\n addressExists(address: string): Promise<boolean>;\n\n addAccount(\n address: string,\n snapId: SnapId,\n handleUserInput: (accepted: boolean) => Promise<void>,\n accountNameSuggestion?: string,\n displayConfirmation?: boolean,\n ): Promise<void>;\n\n removeAccount(\n address: string,\n snapId: SnapId,\n handleUserInput: (accepted: boolean) => Promise<void>,\n ): Promise<void>;\n\n redirectUser(snapId: SnapId, url: string, message: string): Promise<void>;\n};\n\n/**\n * Keyring bridge implementation to support Snaps.\n */\nexport class SnapKeyring extends EventEmitter {\n static type: string = SNAP_KEYRING_TYPE;\n\n type: string;\n\n /**\n * Client used to call the Snap keyring.\n */\n #snapClient: KeyringSnapControllerClient;\n\n /**\n * Mapping between account IDs and an object that contains the associated\n * account object and Snap ID.\n */\n #accounts: SnapIdMap<{\n account: KeyringAccount;\n snapId: SnapId;\n }>;\n\n /**\n * Mapping between request IDs and their deferred promises.\n */\n #requests: SnapIdMap<{\n promise: DeferredPromise<any>;\n snapId: SnapId;\n }>;\n\n /**\n * Callbacks used to interact with other components.\n */\n #callbacks: SnapKeyringCallbacks;\n\n /**\n * Create a new Snap keyring.\n *\n * @param controller - Snaps controller.\n * @param callbacks - Callbacks used to interact with other components.\n * @returns A new Snap keyring.\n */\n constructor(controller: SnapController, callbacks: SnapKeyringCallbacks) {\n super();\n this.type = SnapKeyring.type;\n this.#snapClient = new KeyringSnapControllerClient({ controller });\n this.#requests = new SnapIdMap();\n this.#accounts = new SnapIdMap();\n this.#callbacks = callbacks;\n }\n\n /**\n * Handle an Account Created event from a Snap.\n *\n * @param snapId - Snap ID.\n * @param message - Event message.\n * @returns `null`.\n */\n async #handleAccountCreated(\n snapId: SnapId,\n message: SnapMessage,\n ): Promise<null> {\n assert(message, AccountCreatedEventStruct);\n const { account, accountNameSuggestion, displayConfirmation } =\n message.params;\n\n // The UI still uses the account address to identify accounts, so we need\n // to block the creation of duplicate accounts for now to prevent accounts\n // from being overwritten.\n if (await this.#callbacks.addressExists(account.address.toLowerCase())) {\n throw new Error(`Account address '${account.address}' already exists`);\n }\n\n // A Snap could try to create an account with a different address but with\n // an existing ID, so the above test only is not enough.\n if (this.#accounts.has(snapId, account.id)) {\n throw new Error(`Account '${account.id}' already exists`);\n }\n\n await this.#callbacks.addAccount(\n account.address.toLowerCase(),\n snapId,\n async (accepted: boolean) => {\n if (accepted) {\n this.#accounts.set(account.id, { account, snapId });\n await this.#callbacks.saveState();\n }\n },\n accountNameSuggestion,\n displayConfirmation,\n );\n return null;\n }\n\n /**\n * Handle an Account Updated event from a Snap.\n *\n * @param snapId - Snap ID.\n * @param message - Event message.\n * @returns `null`.\n */\n async #handleAccountUpdated(\n snapId: SnapId,\n message: SnapMessage,\n ): Promise<null> {\n assert(message, AccountUpdatedEventStruct);\n const { account: newAccount } = message.params;\n const { account: oldAccount } =\n this.#accounts.get(snapId, newAccount.id) ??\n throwError(`Account '${newAccount.id}' not found`);\n\n // The address of the account cannot be changed. In the future, we will\n // support changing the address of an account since it will be required to\n // support UTXO-based chains.\n if (!equalsIgnoreCase(oldAccount.address, newAccount.address)) {\n throw new Error(`Cannot change address of account '${newAccount.id}'`);\n }\n\n this.#accounts.set(newAccount.id, { account: newAccount, snapId });\n await this.#callbacks.saveState();\n return null;\n }\n\n /**\n * Handle an Account Deleted event from a Snap.\n *\n * @param snapId - Snap ID.\n * @param message - Event message.\n * @returns `null`.\n */\n async #handleAccountDeleted(\n snapId: SnapId,\n message: SnapMessage,\n ): Promise<null> {\n assert(message, AccountDeletedEventStruct);\n const { id } = message.params;\n const entry = this.#accounts.get(snapId, id);\n\n // We can ignore the case where the account was already removed from the\n // keyring, making the deletion idempotent.\n //\n // This happens when the keyring calls the Snap to delete an account, and\n // the Snap calls the keyring back with an `AccountDeleted` event.\n if (entry === undefined) {\n return null;\n }\n\n // At this point we know that the account exists, so we can safely\n // destructure it.\n const {\n account: { address },\n } = entry;\n\n await this.#callbacks.removeAccount(\n address.toLowerCase(),\n snapId,\n async (accepted) => {\n if (accepted) {\n await this.#callbacks.saveState();\n }\n },\n );\n return null;\n }\n\n /**\n * Handle an Request Approved event from a Snap.\n *\n * @param snapId - Snap ID.\n * @param message - Event message.\n * @returns `null`.\n */\n async #handleRequestApproved(\n snapId: SnapId,\n message: SnapMessage,\n ): Promise<null> {\n assert(message, RequestApprovedEventStruct);\n const { id, result } = message.params;\n const { promise } =\n this.#requests.get(snapId, id) ?? throwError(`Request '${id}' not found`);\n\n this.#requests.delete(snapId, id);\n promise.resolve(result);\n return null;\n }\n\n /**\n * Handle an Request Rejected event from a Snap.\n *\n * @param snapId - Snap ID.\n * @param message - Event message.\n * @returns `null`.\n */\n async #handleRequestRejected(\n snapId: SnapId,\n message: SnapMessage,\n ): Promise<null> {\n assert(message, RequestRejectedEventStruct);\n const { id } = message.params;\n const { promise } =\n this.#requests.get(snapId, id) ?? throwError(`Request '${id}' not found`);\n\n this.#requests.delete(snapId, id);\n promise.reject(new Error(`Request rejected by user or snap.`));\n return null;\n }\n\n /**\n * Handle a message from a Snap.\n *\n * @param snapId - ID of the Snap.\n * @param message - Message sent by the Snap.\n * @returns The execution result.\n */\n async handleKeyringSnapMessage(\n snapId: SnapId,\n message: SnapMessage,\n ): Promise<Json> {\n assert(message, SnapMessageStruct);\n switch (message.method) {\n case KeyringEvent.AccountCreated: {\n return this.#handleAccountCreated(snapId, message);\n }\n\n case KeyringEvent.AccountUpdated: {\n return this.#handleAccountUpdated(snapId, message);\n }\n\n case KeyringEvent.AccountDeleted: {\n return this.#handleAccountDeleted(snapId, message);\n }\n\n case KeyringEvent.RequestApproved: {\n return this.#handleRequestApproved(snapId, message);\n }\n\n case KeyringEvent.RequestRejected: {\n return this.#handleRequestRejected(snapId, message);\n }\n\n default:\n throw new Error(`Method not supported: ${message.method}`);\n }\n }\n\n /**\n * Serialize the keyring state.\n *\n * @returns Serialized keyring state.\n */\n async serialize(): Promise<KeyringState> {\n return {\n accounts: this.#accounts.toObject(),\n };\n }\n\n /**\n * Deserialize the keyring state into this keyring.\n *\n * @param state - Serialized keyring state.\n */\n async deserialize(state: KeyringState | undefined): Promise<void> {\n // If the state is undefined, it means that this is a new keyring, so we\n // don't need to do anything.\n if (state === undefined) {\n return;\n }\n this.#accounts = SnapIdMap.fromObject(state.accounts);\n }\n\n /**\n * Get the addresses of the accounts in this keyring.\n *\n * @returns The addresses of the accounts in this keyring.\n */\n async getAccounts(): Promise<string[]> {\n return unique(\n [...this.#accounts.values()].map(({ account }) =>\n account.address.toLowerCase(),\n ),\n );\n }\n\n /**\n * Get the addresses of the accounts associated with a given Snap.\n *\n * @param snapId - Snap ID to filter by.\n * @returns The addresses of the accounts associated with the given Snap.\n */\n async getAccountsBySnapId(snapId: SnapId): Promise<string[]> {\n return unique(\n [...this.#accounts.values()]\n .filter(({ snapId: accountSnapId }) => accountSnapId === snapId)\n .map(({ account }) => account.address.toLowerCase()),\n );\n }\n\n /**\n * Submit a request to a Snap.\n *\n * @param opts - Request options.\n * @param opts.address - Account address.\n * @param opts.method - Method to call.\n * @param opts.params - Method parameters.\n * @param opts.chainId - Selected chain ID (CAIP-2).\n * @param opts.expectSync - Whether the request should be synchronous.\n * @returns Promise that resolves to the result of the method call.\n */\n async #submitRequest<Response extends Json>({\n address,\n method,\n params,\n chainId = '',\n expectSync = false,\n }: {\n address: string;\n method: string;\n params?: Json[] | Record<string, Json>;\n chainId?: string;\n expectSync?: boolean;\n }): Promise<Json> {\n const { account, snapId } = this.#resolveAddress(address);\n if (!this.#hasMethod(account, method as AccountMethod)) {\n throw new Error(\n `Method '${method}' not supported for account ${account.address}`,\n );\n }\n\n const requestId = uuid();\n\n // Create the promise before calling the Snap to prevent a race condition\n // where the Snap responds before we have a chance to create it.\n const promise = this.#createRequestPromise<Response>(requestId, snapId);\n\n const response = await this.#submitSnapRequest({\n snapId,\n requestId,\n account,\n method: method as AccountMethod,\n params,\n chainId,\n });\n\n // Some methods, like the ones used to prepare and patch user operations,\n // require the Snap to answer synchronously in order to work with the\n // confirmation flow. This check lets the caller enforce this behavior.\n if (expectSync && response.pending) {\n throw new Error(\n `Request '${requestId}' to snap '${snapId}' is pending and expectSync is true.`,\n );\n }\n\n // If the Snap answers synchronously, the promise must be removed from the\n // map to prevent a leak.\n if (!response.pending) {\n return this.#handleSyncResponse(response, requestId, snapId);\n }\n\n // If the Snap answers asynchronously, we will inform the user with a redirect\n if (response.redirect?.message || response.redirect?.url) {\n await this.#handleAsyncResponse(response.redirect, snapId);\n }\n\n return promise.promise;\n }\n\n /**\n * Check if an account supports the given method.\n *\n * @param account - The account object to check for method support.\n * @param method - The Ethereum method to validate.\n * @returns `true` if the method is supported, `false` otherwise.\n */\n #hasMethod(account: KeyringAccount, method: AccountMethod): boolean {\n return (account.methods as AccountMethod[]).includes(method);\n }\n\n /**\n * Creates a promise for a request and adds it to the map of requests.\n *\n * @param requestId - The unique identifier for the request.\n * @param snapId - The Snap ID associated with the request.\n * @returns A DeferredPromise instance.\n */\n #createRequestPromise<Response>(\n requestId: string,\n snapId: SnapId,\n ): DeferredPromise<Response> {\n const promise = new DeferredPromise<Response>();\n this.#requests.set(requestId, { promise, snapId });\n return promise;\n }\n\n /**\n * Submits a request to a Snap.\n *\n * @param options - The options for the Snap request.\n * @param options.snapId - The Snap ID to submit the request to.\n * @param options.requestId - The unique identifier for the request.\n * @param options.account - The account to use for the request.\n * @param options.method - The Ethereum method to call.\n * @param options.params - The parameters to pass to the method, can be undefined.\n * @param options.chainId - The chain ID to use for the request, can be an empty string.\n * @returns A promise that resolves to the keyring response from the Snap.\n * @throws An error if the Snap fails to respond or if there's an issue with the request submission.\n */\n async #submitSnapRequest({\n snapId,\n requestId,\n account,\n method,\n params,\n chainId,\n }: {\n snapId: SnapId;\n requestId: string;\n account: KeyringAccount;\n method: AccountMethod;\n params?: Json[] | Record<string, Json> | undefined;\n chainId: string;\n }): Promise<KeyringResponse> {\n try {\n const request = {\n id: requestId,\n scope: chainId,\n account: account.id,\n request: {\n method,\n ...(params !== undefined && { params }),\n },\n };\n\n log('Submit Snap request: ', request);\n\n return await this.#snapClient.withSnapId(snapId).submitRequest(request);\n } catch (error) {\n log('Snap Request failed: ', { requestId });\n\n // If the Snap failed to respond, delete the promise to prevent a leak.\n this.#requests.delete(snapId, requestId);\n throw error;\n }\n }\n\n /**\n * Handles the synchronous response from a Snap. If the response indicates the request is not pending, it removes the request from the map.\n *\n * @param response - The response from the Snap.\n * @param response.pending - A boolean indicating if the request is pending should always be false in this context.\n * @param response.result - The result data from the Snap response.\n * @param requestId - The unique identifier for the request.\n * @param snapId - The Snap ID associated with the request.\n * @returns The result from the Snap response.\n */\n #handleSyncResponse(\n response: { pending: false; result: Json },\n requestId: string,\n snapId: SnapId,\n ): Json {\n this.#requests.delete(snapId, requestId);\n return response.result;\n }\n\n /**\n * Handles the async redirect and response from a Snap. Validates the redirect URL and informs the user with a message and URL if provided.\n *\n * @param redirect - The redirect information including message and URL.\n * @param redirect.message - The message to show to the user if provided.\n * @param redirect.url - The URL to redirect the user to if provided.\n * @param snapId - The Snap ID associated with the request.\n * @throws An error if the redirect URL is not an allowed origin for the Snap.\n */\n async #handleAsyncResponse(\n redirect: { message?: string; url?: string },\n snapId: SnapId,\n ) {\n const { message = '', url = '' } = redirect;\n if (url) {\n this.#validateRedirectUrl(url, snapId);\n }\n await this.#callbacks.redirectUser(snapId, url, message);\n }\n\n /**\n * Validates if the redirect URL is in the Snap's allowed origins.\n *\n * @param url - The URL to validate.\n * @param snapId - The Snap ID to check allowed origins for.\n * @throws An error if the URL's origin is not in the Snap's allowed origins.\n */\n #validateRedirectUrl(url: string, snapId: SnapId) {\n const { origin } = new URL(url);\n const snap = this.#snapClient.getController().get(snapId);\n if (!snap) {\n throw new Error(`Snap '${snapId}' not found.`);\n }\n const allowedOrigins = this.#getSnapAllowedOrigins(snap);\n if (!allowedOrigins.includes(origin)) {\n throw new Error(\n `Redirect URL domain '${origin}' is not an allowed origin by snap '${snapId}'`,\n );\n }\n }\n\n /**\n * Sign a transaction.\n *\n * @param address - Sender's address.\n * @param transaction - Transaction.\n * @param _opts - Transaction options (not used).\n */\n async signTransaction(\n address: string,\n transaction: TypedTransaction,\n _opts = {},\n ): Promise<Json | TypedTransaction> {\n const chainId = transaction.common.chainId();\n const tx = toJson({\n ...transaction.toJSON(),\n from: address,\n type: `0x${transaction.type.toString(16)}`,\n chainId: bigIntToHex(chainId),\n });\n\n const signedTx = await this.#submitRequest({\n address,\n method: EthMethod.SignTransaction,\n params: [tx],\n chainId: toCaipChainId(KnownCaipNamespace.Eip155, `${chainId}`),\n });\n\n // ! It's *** CRITICAL *** that we mask the signature here, otherwise the\n // ! Snap could overwrite the transaction.\n const signature = mask(\n signedTx,\n object({\n r: string(),\n s: string(),\n v: string(),\n }),\n );\n\n return TransactionFactory.fromTxData({\n ...(tx as Record<string, Json>),\n r: signature.r,\n s: signature.s,\n v: signature.v,\n });\n }\n\n /**\n * Sign a typed data message.\n *\n * @param address - Signer's address.\n * @param data - Data to sign.\n * @param opts - Signing options.\n * @returns The signature.\n */\n async signTypedData(\n address: string,\n data: Record<string, unknown>[] | TypedDataV1 | TypedMessage<any>,\n opts = { version: SignTypedDataVersion.V1 },\n ): Promise<string> {\n const methods = {\n [SignTypedDataVersion.V1]: EthMethod.SignTypedDataV1,\n [SignTypedDataVersion.V3]: EthMethod.SignTypedDataV3,\n [SignTypedDataVersion.V4]: EthMethod.SignTypedDataV4,\n };\n\n // Use 'V1' by default to match other keyring implementations. V1 will be\n // used if the version is not specified or not supported.\n const method = methods[opts.version] || EthMethod.SignTypedDataV1;\n\n // Extract chain ID as if it was a typed message (as defined by EIP-712), if\n // input is not a typed message, then chain ID will be undefined!\n const chainId = (data as TypedMessage<any>).domain?.chainId;\n\n return strictMask(\n await this.#submitRequest({\n address,\n method,\n params: toJson<Json[]>([address, data]),\n ...(chainId === undefined\n ? {}\n : {\n chainId: toCaipChainId(KnownCaipNamespace.Eip155, `${chainId}`),\n }),\n }),\n EthBytesStruct,\n );\n }\n\n /**\n * Sign a message.\n *\n * @param address - Signer's address.\n * @param hash - Data to sign.\n * @returns The signature.\n */\n async signMessage(address: string, hash: any): Promise<string> {\n return strictMask(\n await this.#submitRequest({\n address,\n method: EthMethod.Sign,\n params: toJson<Json[]>([address, hash]),\n }),\n EthBytesStruct,\n );\n }\n\n /**\n * Sign a personal message.\n *\n * Note: KeyringController says this should return a Buffer but it actually\n * expects a string.\n *\n * @param address - Signer's address.\n * @param data - Data to sign.\n * @returns Promise of the signature.\n */\n async signPersonalMessage(address: string, data: any): Promise<string> {\n return strictMask(\n await this.#submitRequest({\n address,\n method: EthMethod.PersonalSign,\n params: toJson<Json[]>([data, address]),\n }),\n EthBytesStruct,\n );\n }\n\n /**\n * Convert a base transaction to a base UserOperation.\n *\n * @param address - Address of the sender.\n * @param transactions - Base transactions to include in the UserOperation.\n * @param context - Keyring execution context.\n * @returns A pseudo-UserOperation that can be used to construct a real.\n */\n async prepareUserOperation(\n address: string,\n transactions: EthBaseTransaction[],\n context: KeyringExecutionContext,\n ): Promise<EthBaseUserOperation> {\n return strictMask(\n await this.#submitRequest({\n address,\n method: EthMethod.PrepareUserOperation,\n params: toJson<Json[]>(transactions),\n expectSync: true,\n // We assume the chain ID is already well formatted\n chainId: toCaipChainId(KnownCaipNamespace.Eip155, context.chainId),\n }),\n EthBaseUserOperationStruct,\n );\n }\n\n /**\n * Patches properties of a UserOperation. Currently, only the\n * `paymasterAndData` can be patched.\n *\n * @param address - Address of the sender.\n * @param userOp - UserOperation to patch.\n * @param context - Keyring execution context.\n * @returns A patch to apply to the UserOperation.\n */\n async patchUserOperation(\n address: string,\n userOp: EthUserOperation,\n context: KeyringExecutionContext,\n ): Promise<EthUserOperationPatch> {\n return strictMask(\n await this.#submitRequest({\n address,\n method: EthMethod.PatchUserOperation,\n params: toJson<Json[]>([userOp]),\n expectSync: true,\n // We assume the chain ID is already well formatted\n chainId: toCaipChainId(KnownCaipNamespace.Eip155, context.chainId),\n }),\n EthUserOperationPatchStruct,\n );\n }\n\n /**\n * Signs an UserOperation.\n *\n * @param address - Address of the sender.\n * @param userOp - UserOperation to sign.\n * @param context - Leyring execution context.\n * @returns The signature of the UserOperation.\n */\n async signUserOperation(\n address: string,\n userOp: EthUserOperation,\n context: KeyringExecutionContext,\n ): Promise<string> {\n return strictMask(\n await this.#submitRequest({\n address,\n method: EthMethod.SignUserOperation,\n params: toJson<Json[]>([userOp]),\n // We assume the chain ID is already well formatted\n chainId: toCaipChainId(KnownCaipNamespace.Eip155, context.chainId),\n }),\n EthBytesStruct,\n );\n }\n\n /**\n * Gets the private data associated with the given address so\n * that it may be exported.\n *\n * If this keyring contains duplicate public keys the first\n * matching address is exported.\n *\n * Used by the UI to export an account.\n *\n * @param _address - Address of the account to export.\n */\n exportAccount(_address: string): [Uint8Array, Json] | undefined {\n throw new Error('Exporting accounts from snaps is not supported.');\n }\n\n /**\n * Removes the account matching the given address.\n *\n * @param address - Address of the account to remove.\n */\n async removeAccount(address: string): Promise<void> {\n const { account, snapId } = this.#resolveAddress(address);\n\n // Always remove the account from the maps, even if the Snap is going to\n // fail to delete it.\n this.#accounts.delete(snapId, account.id);\n\n try {\n await this.#snapClient.withSnapId(snapId).deleteAccount(account.id);\n } catch (error) {\n // If the Snap failed to delete the account, log the error and continue\n // with the account deletion, otherwise the account will be stuck in the\n // keyring.\n console.error(\n `Account '${address}' may not have been removed from snap '${snapId}':`,\n error,\n );\n }\n }\n\n /**\n * Resolve an address to an account and Snap ID.\n *\n * @param address - Address of the account to resolve.\n * @returns Account and Snap ID. Throws if the account or Snap ID is not\n * found.\n */\n #resolveAddress(address: string): {\n account: KeyringAccount;\n snapId: SnapId;\n } {\n return (\n [...this.#accounts.values()].find(({ account }) =>\n equalsIgnoreCase(account.address, address),\n ) ?? throwError(`Account '${address}' not found`)\n );\n }\n\n /**\n * Get the metadata of a Snap keyring account.\n *\n * @param snapId - Snap ID.\n * @returns The Snap metadata or undefined if the Snap cannot be found.\n */\n #getSnapMetadata(\n snapId: SnapId,\n ): InternalAccount['metadata']['snap'] | undefined {\n const snap = this.#snapClient.getController().get(snapId);\n return snap\n ? { id: snapId, name: snap.manifest.proposedName, enabled: snap.enabled }\n : undefined;\n }\n\n /**\n * Get the allowed origins of a Snap.\n *\n * @param snap - Snap.\n * @returns The allowed origins of the Snap.\n */\n #getSnapAllowedOrigins(snap: Snap): string[] {\n return (\n snap.manifest.initialPermissions['endowment:keyring']?.allowedOrigins ??\n []\n );\n }\n\n /**\n * Return an internal account object for a given address.\n *\n * @param address - Address of the account to return.\n * @returns An internal account object for the given address.\n */\n getAccountByAddress(address: string): InternalAccount | undefined {\n const accounts = this.listAccounts();\n return accounts.find(({ address: accountAddress }) =>\n equalsIgnoreCase(accountAddress, address),\n );\n }\n\n /**\n * List all Snap keyring accounts.\n *\n * @returns An array containing all Snap keyring accounts.\n */\n listAccounts(): InternalAccount[] {\n return [...this.#accounts.values()].map(({ account, snapId }) => {\n const snap = this.#getSnapMetadata(snapId);\n return {\n ...account,\n // TODO: Do not convert the address to lowercase.\n //\n // This is a workaround to support the current UI which expects the\n // account address to be lowercase. This workaround should be removed\n // once we migrated the UI to use the account ID instead of the account\n // address.\n address: account.address.toLowerCase(),\n metadata: {\n name: '',\n importTime: 0,\n keyring: {\n type: this.type,\n },\n ...(snap !== undefined && { snap }),\n },\n };\n });\n }\n}\n"]}
1
+ {"version":3,"file":"SnapKeyring.js","sourceRoot":"","sources":["../src/SnapKeyring.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-redundant-type-constituents */\n// This rule seems to be triggering a false positive. Possibly eslint is not\n// inferring the EthMethod, BtcMethod, and InternalAccount types correctly.\n\nimport type { TypedTransaction } from '@ethereumjs/tx';\nimport { TransactionFactory } from '@ethereumjs/tx';\nimport type { TypedDataV1, TypedMessage } from '@metamask/eth-sig-util';\nimport { SignTypedDataVersion } from '@metamask/eth-sig-util';\nimport type {\n BtcMethod,\n EthBaseTransaction,\n EthBaseUserOperation,\n EthUserOperation,\n EthUserOperationPatch,\n InternalAccount,\n KeyringAccount,\n KeyringExecutionContext,\n KeyringResponse,\n} from '@metamask/keyring-api';\nimport {\n AccountCreatedEventStruct,\n AccountDeletedEventStruct,\n AccountUpdatedEventStruct,\n EthBaseUserOperationStruct,\n EthBytesStruct,\n EthMethod,\n EthUserOperationPatchStruct,\n KeyringEvent,\n RequestApprovedEventStruct,\n RequestRejectedEventStruct,\n} from '@metamask/keyring-api';\nimport type { SnapController } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport type { Snap } from '@metamask/snaps-utils';\nimport { assert, mask, object, string } from '@metamask/superstruct';\nimport type { Json } from '@metamask/utils';\nimport {\n bigIntToHex,\n KnownCaipNamespace,\n toCaipChainId,\n} from '@metamask/utils';\nimport { EventEmitter } from 'events';\nimport { v4 as uuid } from 'uuid';\n\nimport { DeferredPromise } from './DeferredPromise';\nimport { KeyringSnapControllerClient } from './KeyringSnapControllerClient';\nimport { projectLogger as log } from './logger';\nimport { SnapIdMap } from './SnapIdMap';\nimport type { SnapMessage } from './types';\nimport { SnapMessageStruct } from './types';\nimport {\n equalsIgnoreCase,\n sanitizeUrl,\n strictMask,\n throwError,\n toJson,\n unique,\n} from './util';\n\nexport const SNAP_KEYRING_TYPE = 'Snap Keyring';\n\n// TODO: to be removed when this is added to the keyring-api\n\ntype AccountMethod = EthMethod | BtcMethod;\n\n/**\n * Snap keyring state.\n *\n * This state is persisted by the keyring controller and passed to the Snap\n * keyring when it's created.\n */\nexport type KeyringState = {\n accounts: Record<string, { account: KeyringAccount; snapId: SnapId }>;\n};\n\n/**\n * Snap keyring callbacks.\n *\n * These callbacks are used to interact with other components.\n */\nexport type SnapKeyringCallbacks = {\n saveState: () => Promise<void>;\n\n addressExists(address: string): Promise<boolean>;\n\n addAccount(\n address: string,\n snapId: SnapId,\n handleUserInput: (accepted: boolean) => Promise<void>,\n accountNameSuggestion?: string,\n displayConfirmation?: boolean,\n ): Promise<void>;\n\n removeAccount(\n address: string,\n snapId: SnapId,\n handleUserInput: (accepted: boolean) => Promise<void>,\n ): Promise<void>;\n\n redirectUser(snapId: SnapId, url: string, message: string): Promise<void>;\n};\n\n/**\n * Keyring bridge implementation to support Snaps.\n */\nexport class SnapKeyring extends EventEmitter {\n static type: string = SNAP_KEYRING_TYPE;\n\n type: string;\n\n /**\n * Client used to call the Snap keyring.\n */\n readonly #snapClient: KeyringSnapControllerClient;\n\n /**\n * Mapping between account IDs and an object that contains the associated\n * account object and Snap ID.\n */\n #accounts: SnapIdMap<{\n account: KeyringAccount;\n snapId: SnapId;\n }>;\n\n /**\n * Mapping between request IDs and their deferred promises.\n */\n readonly #requests: SnapIdMap<{\n promise: DeferredPromise<any>;\n snapId: SnapId;\n }>;\n\n /**\n * Callbacks used to interact with other components.\n */\n readonly #callbacks: SnapKeyringCallbacks;\n\n /**\n * Create a new Snap keyring.\n *\n * @param controller - Snaps controller.\n * @param callbacks - Callbacks used to interact with other components.\n * @returns A new Snap keyring.\n */\n constructor(controller: SnapController, callbacks: SnapKeyringCallbacks) {\n super();\n this.type = SnapKeyring.type;\n this.#snapClient = new KeyringSnapControllerClient({ controller });\n this.#requests = new SnapIdMap();\n this.#accounts = new SnapIdMap();\n this.#callbacks = callbacks;\n }\n\n /**\n * Handle an Account Created event from a Snap.\n *\n * @param snapId - Snap ID.\n * @param message - Event message.\n * @returns `null`.\n */\n async #handleAccountCreated(\n snapId: SnapId,\n message: SnapMessage,\n ): Promise<null> {\n assert(message, AccountCreatedEventStruct);\n const { account, accountNameSuggestion, displayConfirmation } =\n message.params;\n\n // The UI still uses the account address to identify accounts, so we need\n // to block the creation of duplicate accounts for now to prevent accounts\n // from being overwritten.\n if (await this.#callbacks.addressExists(account.address.toLowerCase())) {\n throw new Error(`Account address '${account.address}' already exists`);\n }\n\n // A Snap could try to create an account with a different address but with\n // an existing ID, so the above test only is not enough.\n if (this.#accounts.has(snapId, account.id)) {\n throw new Error(`Account '${account.id}' already exists`);\n }\n\n await this.#callbacks.addAccount(\n account.address.toLowerCase(),\n snapId,\n async (accepted: boolean) => {\n if (accepted) {\n this.#accounts.set(account.id, { account, snapId });\n await this.#callbacks.saveState();\n }\n },\n accountNameSuggestion,\n displayConfirmation,\n );\n return null;\n }\n\n /**\n * Handle an Account Updated event from a Snap.\n *\n * @param snapId - Snap ID.\n * @param message - Event message.\n * @returns `null`.\n */\n async #handleAccountUpdated(\n snapId: SnapId,\n message: SnapMessage,\n ): Promise<null> {\n assert(message, AccountUpdatedEventStruct);\n const { account: newAccount } = message.params;\n const { account: oldAccount } =\n this.#accounts.get(snapId, newAccount.id) ??\n throwError(`Account '${newAccount.id}' not found`);\n\n // The address of the account cannot be changed. In the future, we will\n // support changing the address of an account since it will be required to\n // support UTXO-based chains.\n if (!equalsIgnoreCase(oldAccount.address, newAccount.address)) {\n throw new Error(`Cannot change address of account '${newAccount.id}'`);\n }\n\n this.#accounts.set(newAccount.id, { account: newAccount, snapId });\n await this.#callbacks.saveState();\n return null;\n }\n\n /**\n * Handle an Account Deleted event from a Snap.\n *\n * @param snapId - Snap ID.\n * @param message - Event message.\n * @returns `null`.\n */\n async #handleAccountDeleted(\n snapId: SnapId,\n message: SnapMessage,\n ): Promise<null> {\n assert(message, AccountDeletedEventStruct);\n const { id } = message.params;\n const entry = this.#accounts.get(snapId, id);\n\n // We can ignore the case where the account was already removed from the\n // keyring, making the deletion idempotent.\n //\n // This happens when the keyring calls the Snap to delete an account, and\n // the Snap calls the keyring back with an `AccountDeleted` event.\n if (entry === undefined) {\n return null;\n }\n\n // At this point we know that the account exists, so we can safely\n // destructure it.\n const {\n account: { address },\n } = entry;\n\n await this.#callbacks.removeAccount(\n address.toLowerCase(),\n snapId,\n async (accepted) => {\n if (accepted) {\n await this.#callbacks.saveState();\n }\n },\n );\n return null;\n }\n\n /**\n * Handle an Request Approved event from a Snap.\n *\n * @param snapId - Snap ID.\n * @param message - Event message.\n * @returns `null`.\n */\n async #handleRequestApproved(\n snapId: SnapId,\n message: SnapMessage,\n ): Promise<null> {\n assert(message, RequestApprovedEventStruct);\n const { id, result } = message.params;\n const { promise } =\n this.#requests.get(snapId, id) ?? throwError(`Request '${id}' not found`);\n\n this.#requests.delete(snapId, id);\n promise.resolve(result);\n return null;\n }\n\n /**\n * Handle an Request Rejected event from a Snap.\n *\n * @param snapId - Snap ID.\n * @param message - Event message.\n * @returns `null`.\n */\n async #handleRequestRejected(\n snapId: SnapId,\n message: SnapMessage,\n ): Promise<null> {\n assert(message, RequestRejectedEventStruct);\n const { id } = message.params;\n const { promise } =\n this.#requests.get(snapId, id) ?? throwError(`Request '${id}' not found`);\n\n this.#requests.delete(snapId, id);\n promise.reject(new Error(`Request rejected by user or snap.`));\n return null;\n }\n\n /**\n * Handle a message from a Snap.\n *\n * @param snapId - ID of the Snap.\n * @param message - Message sent by the Snap.\n * @returns The execution result.\n */\n async handleKeyringSnapMessage(\n snapId: SnapId,\n message: SnapMessage,\n ): Promise<Json> {\n assert(message, SnapMessageStruct);\n switch (message.method) {\n case `${KeyringEvent.AccountCreated}`: {\n return this.#handleAccountCreated(snapId, message);\n }\n\n case `${KeyringEvent.AccountUpdated}`: {\n return this.#handleAccountUpdated(snapId, message);\n }\n\n case `${KeyringEvent.AccountDeleted}`: {\n return this.#handleAccountDeleted(snapId, message);\n }\n\n case `${KeyringEvent.RequestApproved}`: {\n return this.#handleRequestApproved(snapId, message);\n }\n\n case `${KeyringEvent.RequestRejected}`: {\n return this.#handleRequestRejected(snapId, message);\n }\n\n default:\n throw new Error(`Method not supported: ${message.method}`);\n }\n }\n\n /**\n * Serialize the keyring state.\n *\n * @returns Serialized keyring state.\n */\n async serialize(): Promise<KeyringState> {\n return {\n accounts: this.#accounts.toObject(),\n };\n }\n\n /**\n * Deserialize the keyring state into this keyring.\n *\n * @param state - Serialized keyring state.\n */\n async deserialize(state: KeyringState | undefined): Promise<void> {\n // If the state is undefined, it means that this is a new keyring, so we\n // don't need to do anything.\n if (state === undefined) {\n return;\n }\n this.#accounts = SnapIdMap.fromObject(state.accounts);\n }\n\n /**\n * Get the addresses of the accounts in this keyring.\n *\n * @returns The addresses of the accounts in this keyring.\n */\n async getAccounts(): Promise<string[]> {\n return unique(\n [...this.#accounts.values()].map(({ account }) =>\n account.address.toLowerCase(),\n ),\n );\n }\n\n /**\n * Get the addresses of the accounts associated with a given Snap.\n *\n * @param snapId - Snap ID to filter by.\n * @returns The addresses of the accounts associated with the given Snap.\n */\n async getAccountsBySnapId(snapId: SnapId): Promise<string[]> {\n return unique(\n [...this.#accounts.values()]\n .filter(({ snapId: accountSnapId }) => accountSnapId === snapId)\n .map(({ account }) => account.address.toLowerCase()),\n );\n }\n\n /**\n * Submit a request to a Snap.\n *\n * @param opts - Request options.\n * @param opts.address - Account address.\n * @param opts.method - Method to call.\n * @param opts.params - Method parameters.\n * @param opts.chainId - Selected chain ID (CAIP-2).\n * @param opts.noPending - Whether the response is allowed to be pending.\n * @returns Promise that resolves to the result of the method call.\n */\n async #submitRequest<Response extends Json>({\n address,\n method,\n params,\n chainId = '',\n noPending = false,\n }: {\n address: string;\n method: string;\n params?: Json[] | Record<string, Json>;\n chainId?: string;\n noPending?: boolean;\n }): Promise<Json> {\n const { account, snapId } = this.#resolveAddress(address);\n if (!this.#hasMethod(account, method as AccountMethod)) {\n throw new Error(\n `Method '${method}' not supported for account ${account.address}`,\n );\n }\n\n const requestId = uuid();\n\n // Create the promise before calling the Snap to prevent a race condition\n // where the Snap responds before we have a chance to create it.\n const promise = this.#createRequestPromise<Response>(requestId, snapId);\n\n const response = await this.#submitSnapRequest({\n snapId,\n requestId,\n account,\n method: method as AccountMethod,\n params,\n chainId,\n });\n\n // Some methods, like the ones used to prepare and patch user operations,\n // require the Snap to answer synchronously in order to work with the\n // confirmation flow. This check lets the caller enforce this behavior.\n if (noPending && response.pending) {\n throw new Error(\n `Request '${requestId}' to snap '${snapId}' is pending and noPending is true.`,\n );\n }\n\n // If the Snap answers synchronously, the promise must be removed from the\n // map to prevent a leak.\n if (!response.pending) {\n return this.#handleSyncResponse(response, requestId, snapId);\n }\n\n // If the Snap answers asynchronously, we will inform the user with a redirect\n if (response.redirect?.message || response.redirect?.url) {\n await this.#handleAsyncResponse(response.redirect, snapId);\n }\n\n return promise.promise;\n }\n\n /**\n * Check if an account supports the given method.\n *\n * @param account - The account object to check for method support.\n * @param method - The Ethereum method to validate.\n * @returns `true` if the method is supported, `false` otherwise.\n */\n #hasMethod(account: KeyringAccount, method: AccountMethod): boolean {\n return (account.methods as AccountMethod[]).includes(method);\n }\n\n /**\n * Creates a promise for a request and adds it to the map of requests.\n *\n * @param requestId - The unique identifier for the request.\n * @param snapId - The Snap ID associated with the request.\n * @returns A DeferredPromise instance.\n */\n #createRequestPromise<Response>(\n requestId: string,\n snapId: SnapId,\n ): DeferredPromise<Response> {\n const promise = new DeferredPromise<Response>();\n this.#requests.set(requestId, { promise, snapId });\n return promise;\n }\n\n /**\n * Submits a request to a Snap.\n *\n * @param options - The options for the Snap request.\n * @param options.snapId - The Snap ID to submit the request to.\n * @param options.requestId - The unique identifier for the request.\n * @param options.account - The account to use for the request.\n * @param options.method - The Ethereum method to call.\n * @param options.params - The parameters to pass to the method, can be undefined.\n * @param options.chainId - The chain ID to use for the request, can be an empty string.\n * @returns A promise that resolves to the keyring response from the Snap.\n * @throws An error if the Snap fails to respond or if there's an issue with the request submission.\n */\n async #submitSnapRequest({\n snapId,\n requestId,\n account,\n method,\n params,\n chainId,\n }: {\n snapId: SnapId;\n requestId: string;\n account: KeyringAccount;\n method: AccountMethod;\n params?: Json[] | Record<string, Json> | undefined;\n chainId: string;\n }): Promise<KeyringResponse> {\n try {\n const request = {\n id: requestId,\n scope: chainId,\n account: account.id,\n request: {\n method,\n ...(params !== undefined && { params }),\n },\n };\n\n log('Submit Snap request: ', request);\n\n return await this.#snapClient.withSnapId(snapId).submitRequest(request);\n } catch (error) {\n log('Snap Request failed: ', { requestId });\n\n // If the Snap failed to respond, delete the promise to prevent a leak.\n this.#requests.delete(snapId, requestId);\n throw error;\n }\n }\n\n /**\n * Handles the synchronous response from a Snap. If the response indicates the request is not pending, it removes the request from the map.\n *\n * @param response - The response from the Snap.\n * @param response.pending - A boolean indicating if the request is pending should always be false in this context.\n * @param response.result - The result data from the Snap response.\n * @param requestId - The unique identifier for the request.\n * @param snapId - The Snap ID associated with the request.\n * @returns The result from the Snap response.\n */\n #handleSyncResponse(\n response: { pending: false; result: Json },\n requestId: string,\n snapId: SnapId,\n ): Json {\n this.#requests.delete(snapId, requestId);\n return response.result;\n }\n\n /**\n * Handles the async redirect and response from a Snap. Validates the redirect URL and informs the user with a message and URL if provided.\n *\n * @param redirect - The redirect information including message and URL.\n * @param redirect.message - The message to show to the user if provided.\n * @param redirect.url - The URL to redirect the user to if provided.\n * @param snapId - The Snap ID associated with the request.\n * @throws An error if the redirect URL is not an allowed origin for the Snap.\n */\n async #handleAsyncResponse(\n redirect: { message?: string; url?: string },\n snapId: SnapId,\n ): Promise<void> {\n const { message = '', url: redirectUrl = '' } = redirect;\n const url = this.#sanitizeRedirectUrl(redirectUrl);\n if (url) {\n this.#validateRedirectUrl(url, snapId);\n }\n await this.#callbacks.redirectUser(snapId, url, message);\n }\n\n /**\n * Sanitize a redirect URL.\n *\n * @param url - The URL to sanitize.\n * @returns The new sanitized redirect URL.\n */\n #sanitizeRedirectUrl(url: string): string {\n // We do check if the URL is empty or not since the Snap might not returns any URL at all.\n return url ? sanitizeUrl(url) : url;\n }\n\n /**\n * Validates if the redirect URL is in the Snap's allowed origins.\n *\n * @param url - The URL to validate.\n * @param snapId - The Snap ID to check allowed origins for.\n * @throws An error if the URL's origin is not in the Snap's allowed origins.\n */\n #validateRedirectUrl(url: string, snapId: SnapId): void {\n const { origin } = new URL(url);\n const snap = this.#snapClient.getController().get(snapId);\n if (!snap) {\n throw new Error(`Snap '${snapId}' not found.`);\n }\n const allowedOrigins = this.#getSnapAllowedOrigins(snap);\n if (!allowedOrigins.includes(origin)) {\n throw new Error(\n `Redirect URL domain '${origin}' is not an allowed origin by snap '${snapId}'`,\n );\n }\n }\n\n /**\n * Sign a transaction.\n *\n * @param address - Sender's address.\n * @param transaction - Transaction.\n * @param _opts - Transaction options (not used).\n * @returns A promise that resolves to the signed transaction.\n */\n async signTransaction(\n address: string,\n transaction: TypedTransaction,\n _opts = {},\n ): Promise<Json | TypedTransaction> {\n const chainId = transaction.common.chainId();\n const tx = toJson({\n ...transaction.toJSON(),\n from: address,\n type: `0x${transaction.type.toString(16)}`,\n chainId: bigIntToHex(chainId),\n });\n\n const signedTx = await this.#submitRequest({\n address,\n method: EthMethod.SignTransaction,\n params: [tx],\n chainId: toCaipChainId(KnownCaipNamespace.Eip155, `${chainId}`),\n });\n\n // ! It's *** CRITICAL *** that we mask the signature here, otherwise the\n // ! Snap could overwrite the transaction.\n const signature = mask(\n signedTx,\n object({\n r: string(),\n s: string(),\n v: string(),\n }),\n );\n\n return TransactionFactory.fromTxData({\n ...(tx as Record<string, Json>),\n r: signature.r,\n s: signature.s,\n v: signature.v,\n });\n }\n\n /**\n * Sign a typed data message.\n *\n * @param address - Signer's address.\n * @param data - Data to sign.\n * @param opts - Signing options.\n * @returns The signature.\n */\n async signTypedData(\n address: string,\n data: Record<string, unknown>[] | TypedDataV1 | TypedMessage<any>,\n opts = { version: SignTypedDataVersion.V1 },\n ): Promise<string> {\n const methods = {\n [SignTypedDataVersion.V1]: EthMethod.SignTypedDataV1,\n [SignTypedDataVersion.V3]: EthMethod.SignTypedDataV3,\n [SignTypedDataVersion.V4]: EthMethod.SignTypedDataV4,\n };\n\n // Use 'V1' by default to match other keyring implementations. V1 will be\n // used if the version is not specified or not supported.\n const method = methods[opts.version] || EthMethod.SignTypedDataV1;\n\n // Extract chain ID as if it was a typed message (as defined by EIP-712), if\n // input is not a typed message, then chain ID will be undefined!\n const chainId = (data as TypedMessage<any>).domain?.chainId;\n\n return strictMask(\n await this.#submitRequest({\n address,\n method,\n params: toJson<Json[]>([address, data]),\n ...(chainId === undefined\n ? {}\n : {\n chainId: toCaipChainId(KnownCaipNamespace.Eip155, `${chainId}`),\n }),\n }),\n EthBytesStruct,\n );\n }\n\n /**\n * Sign a message.\n *\n * @param address - Signer's address.\n * @param hash - Data to sign.\n * @returns The signature.\n */\n async signMessage(address: string, hash: any): Promise<string> {\n return strictMask(\n await this.#submitRequest({\n address,\n method: EthMethod.Sign,\n params: toJson<Json[]>([address, hash]),\n }),\n EthBytesStruct,\n );\n }\n\n /**\n * Sign a personal message.\n *\n * Note: KeyringController says this should return a Buffer but it actually\n * expects a string.\n *\n * @param address - Signer's address.\n * @param data - Data to sign.\n * @returns Promise of the signature.\n */\n async signPersonalMessage(address: string, data: any): Promise<string> {\n return strictMask(\n await this.#submitRequest({\n address,\n method: EthMethod.PersonalSign,\n params: toJson<Json[]>([data, address]),\n }),\n EthBytesStruct,\n );\n }\n\n /**\n * Convert a base transaction to a base UserOperation.\n *\n * @param address - Address of the sender.\n * @param transactions - Base transactions to include in the UserOperation.\n * @param context - Keyring execution context.\n * @returns A pseudo-UserOperation that can be used to construct a real.\n */\n async prepareUserOperation(\n address: string,\n transactions: EthBaseTransaction[],\n context: KeyringExecutionContext,\n ): Promise<EthBaseUserOperation> {\n return strictMask(\n await this.#submitRequest({\n address,\n method: EthMethod.PrepareUserOperation,\n params: toJson<Json[]>(transactions),\n noPending: true,\n // We assume the chain ID is already well formatted\n chainId: toCaipChainId(KnownCaipNamespace.Eip155, context.chainId),\n }),\n EthBaseUserOperationStruct,\n );\n }\n\n /**\n * Patches properties of a UserOperation. Currently, only the\n * `paymasterAndData` can be patched.\n *\n * @param address - Address of the sender.\n * @param userOp - UserOperation to patch.\n * @param context - Keyring execution context.\n * @returns A patch to apply to the UserOperation.\n */\n async patchUserOperation(\n address: string,\n userOp: EthUserOperation,\n context: KeyringExecutionContext,\n ): Promise<EthUserOperationPatch> {\n return strictMask(\n await this.#submitRequest({\n address,\n method: EthMethod.PatchUserOperation,\n params: toJson<Json[]>([userOp]),\n noPending: true,\n // We assume the chain ID is already well formatted\n chainId: toCaipChainId(KnownCaipNamespace.Eip155, context.chainId),\n }),\n EthUserOperationPatchStruct,\n );\n }\n\n /**\n * Signs an UserOperation.\n *\n * @param address - Address of the sender.\n * @param userOp - UserOperation to sign.\n * @param context - Leyring execution context.\n * @returns The signature of the UserOperation.\n */\n async signUserOperation(\n address: string,\n userOp: EthUserOperation,\n context: KeyringExecutionContext,\n ): Promise<string> {\n return strictMask(\n await this.#submitRequest({\n address,\n method: EthMethod.SignUserOperation,\n params: toJson<Json[]>([userOp]),\n // We assume the chain ID is already well formatted\n chainId: toCaipChainId(KnownCaipNamespace.Eip155, context.chainId),\n }),\n EthBytesStruct,\n );\n }\n\n /**\n * Gets the private data associated with the given address so\n * that it may be exported.\n *\n * If this keyring contains duplicate public keys the first\n * matching address is exported.\n *\n * Used by the UI to export an account.\n *\n * @param _address - Address of the account to export.\n */\n exportAccount(_address: string): [Uint8Array, Json] | undefined {\n throw new Error('Exporting accounts from snaps is not supported.');\n }\n\n /**\n * Removes the account matching the given address.\n *\n * @param address - Address of the account to remove.\n */\n async removeAccount(address: string): Promise<void> {\n const { account, snapId } = this.#resolveAddress(address);\n\n // Always remove the account from the maps, even if the Snap is going to\n // fail to delete it.\n this.#accounts.delete(snapId, account.id);\n\n try {\n await this.#snapClient.withSnapId(snapId).deleteAccount(account.id);\n } catch (error) {\n // If the Snap failed to delete the account, log the error and continue\n // with the account deletion, otherwise the account will be stuck in the\n // keyring.\n console.error(\n `Account '${address}' may not have been removed from snap '${snapId}':`,\n error,\n );\n }\n }\n\n /**\n * Resolve an address to an account and Snap ID.\n *\n * @param address - Address of the account to resolve.\n * @returns Account and Snap ID. Throws if the account or Snap ID is not\n * found.\n */\n #resolveAddress(address: string): {\n account: KeyringAccount;\n snapId: SnapId;\n } {\n return (\n [...this.#accounts.values()].find(({ account }) =>\n equalsIgnoreCase(account.address, address),\n ) ?? throwError(`Account '${address}' not found`)\n );\n }\n\n /**\n * Get the metadata of a Snap keyring account.\n *\n * @param snapId - Snap ID.\n * @returns The Snap metadata or undefined if the Snap cannot be found.\n */\n #getSnapMetadata(\n snapId: SnapId,\n ): InternalAccount['metadata']['snap'] | undefined {\n const snap = this.#snapClient.getController().get(snapId);\n return snap\n ? { id: snapId, name: snap.manifest.proposedName, enabled: snap.enabled }\n : undefined;\n }\n\n /**\n * Get the allowed origins of a Snap.\n *\n * @param snap - Snap.\n * @returns The allowed origins of the Snap.\n */\n #getSnapAllowedOrigins(snap: Snap): string[] {\n return (\n snap.manifest.initialPermissions['endowment:keyring']?.allowedOrigins ??\n []\n );\n }\n\n /**\n * Return an internal account object for a given address.\n *\n * @param address - Address of the account to return.\n * @returns An internal account object for the given address.\n */\n getAccountByAddress(address: string): InternalAccount | undefined {\n const accounts = this.listAccounts();\n return accounts.find(({ address: accountAddress }) =>\n equalsIgnoreCase(accountAddress, address),\n );\n }\n\n /**\n * List all Snap keyring accounts.\n *\n * @returns An array containing all Snap keyring accounts.\n */\n listAccounts(): InternalAccount[] {\n return [...this.#accounts.values()].map(({ account, snapId }) => {\n const snap = this.#getSnapMetadata(snapId);\n return {\n ...account,\n // TODO: Do not convert the address to lowercase.\n //\n // This is a workaround to support the current UI which expects the\n // account address to be lowercase. This workaround should be removed\n // once we migrated the UI to use the account ID instead of the account\n // address.\n address: account.address.toLowerCase(),\n metadata: {\n name: '',\n importTime: 0,\n keyring: {\n type: this.type,\n },\n ...(snap !== undefined && { snap }),\n },\n };\n });\n }\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -9,4 +9,4 @@ export declare const SnapMessageStruct: import("@metamask/superstruct").Struct<{
9
9
  /**
10
10
  * Message sent by the snap to manage accounts and requests.
11
11
  */
12
- export declare type SnapMessage = Infer<typeof SnapMessageStruct>;
12
+ export type SnapMessage = Infer<typeof SnapMessageStruct>;
package/dist/util.d.ts CHANGED
@@ -50,3 +50,10 @@ export declare function throwError(message: string): never;
50
50
  * @returns `true` if the strings are equal, ignoring case. `false` otherwise.
51
51
  */
52
52
  export declare function equalsIgnoreCase(a: string, b: string): boolean;
53
+ /**
54
+ * Sanitize a URL.
55
+ *
56
+ * @param url - The URL to sanitize.
57
+ * @returns The new sanitized redirect URL.
58
+ */
59
+ export declare function sanitizeUrl(url: string): string;
package/dist/util.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.equalsIgnoreCase = exports.throwError = exports.ensureDefined = exports.toJson = exports.unique = exports.strictMask = void 0;
3
+ exports.sanitizeUrl = exports.equalsIgnoreCase = exports.throwError = exports.ensureDefined = exports.toJson = exports.unique = exports.strictMask = void 0;
4
4
  const superstruct_1 = require("@metamask/superstruct");
5
5
  /**
6
6
  * Assert that a value is valid according to a struct.
@@ -73,4 +73,17 @@ function equalsIgnoreCase(a, b) {
73
73
  return a.toLowerCase() === b.toLowerCase();
74
74
  }
75
75
  exports.equalsIgnoreCase = equalsIgnoreCase;
76
+ /**
77
+ * Sanitize a URL.
78
+ *
79
+ * @param url - The URL to sanitize.
80
+ * @returns The new sanitized redirect URL.
81
+ */
82
+ function sanitizeUrl(url) {
83
+ // For now, we only re-create the URL object which should take care of most of the sanitizing, like replacing
84
+ // upper-cased letters by their lower-cased counterparts in the "hostname" part.
85
+ const saferUrl = new URL(url);
86
+ return saferUrl.toString();
87
+ }
88
+ exports.sanitizeUrl = sanitizeUrl;
76
89
  //# sourceMappingURL=util.js.map
package/dist/util.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;;AACA,uDAA+C;AAG/C;;;;;;;;;;GAUG;AACH,SAAgB,UAAU,CACxB,KAAc,EACd,MAA4B,EAC5B,OAAgB;IAEhB,IAAA,oBAAM,EAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,KAAK,CAAC;AACf,CAAC;AAPD,gCAOC;AAED;;;;;GAKG;AACH,SAAgB,MAAM,CAAO,KAA8B;IACzD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;AAC7B,CAAC;AAFD,wBAEC;AAED;;;;;;;;;GASG;AACH,SAAgB,MAAM,CAA2B,KAAU;IACzD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAS,CAAC;AACnD,CAAC;AAFD,wBAEC;AAED;;;;GAIG;AACH,SAAgB,aAAa,CAC3B,KAAuB;IAEvB,IAAI,KAAK,KAAK,SAAS,EAAE;QACvB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;KAC1C;AACH,CAAC;AAND,sCAMC;AAED;;;;GAIG;AACH,SAAgB,UAAU,CAAC,OAAe;IACxC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;AAC3B,CAAC;AAFD,gCAEC;AAED;;;;;;GAMG;AACH,SAAgB,gBAAgB,CAAC,CAAS,EAAE,CAAS;IACnD,OAAO,CAAC,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;AAC7C,CAAC;AAFD,4CAEC","sourcesContent":["import type { Struct } from '@metamask/superstruct';\nimport { assert } from '@metamask/superstruct';\nimport type { Json } from '@metamask/utils';\n\n/**\n * Assert that a value is valid according to a struct.\n *\n * It is similar to superstruct's mask function, but it does not ignore extra\n * properties.\n *\n * @param value - Value to check.\n * @param struct - Struct to validate the value against.\n * @param message - Error message to throw if the value is not valid.\n * @returns The value if it is valid.\n */\nexport function strictMask<Type, Schema>(\n value: unknown,\n struct: Struct<Type, Schema>,\n message?: string,\n): Type {\n assert(value, struct, message);\n return value;\n}\n\n/**\n * Remove duplicate entries from an array.\n *\n * @param array - Array to remove duplicates from.\n * @returns Array with duplicates removed.\n */\nexport function unique<Type>(array: Type[] | Iterable<Type>): Type[] {\n return [...new Set(array)];\n}\n\n/**\n * Convert a value to a valid JSON object.\n *\n * The function chains JSON.stringify and JSON.parse to ensure that the result\n * is a valid JSON object. In objects, undefined values are removed, and in\n * arrays, they are replaced with null.\n *\n * @param value - Value to convert to JSON.\n * @returns JSON representation of the value.\n */\nexport function toJson<Type extends Json = Json>(value: any): Type {\n return JSON.parse(JSON.stringify(value)) as Type;\n}\n\n/**\n * Asserts that the given value is defined.\n *\n * @param value - Value to check.\n */\nexport function ensureDefined<Type>(\n value: Type | undefined,\n): asserts value is Type {\n if (value === undefined) {\n throw new Error('Argument is undefined');\n }\n}\n\n/**\n * Helper function that throws an error.\n *\n * @param message - Error message to throw.\n */\nexport function throwError(message: string): never {\n throw new Error(message);\n}\n\n/**\n * Compares two strings for equality, ignoring case.\n *\n * @param a - The first string to compare.\n * @param b - The second string to compare.\n * @returns `true` if the strings are equal, ignoring case. `false` otherwise.\n */\nexport function equalsIgnoreCase(a: string, b: string): boolean {\n return a.toLowerCase() === b.toLowerCase();\n}\n"]}
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;;AACA,uDAA+C;AAG/C;;;;;;;;;;GAUG;AACH,SAAgB,UAAU,CACxB,KAAc,EACd,MAA4B,EAC5B,OAAgB;IAEhB,IAAA,oBAAM,EAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,KAAK,CAAC;AACf,CAAC;AAPD,gCAOC;AAED;;;;;GAKG;AACH,SAAgB,MAAM,CAAO,KAA8B;IACzD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;AAC7B,CAAC;AAFD,wBAEC;AAED;;;;;;;;;GASG;AACH,SAAgB,MAAM,CAA2B,KAAU;IACzD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAS,CAAC;AACnD,CAAC;AAFD,wBAEC;AAED;;;;GAIG;AACH,SAAgB,aAAa,CAC3B,KAAuB;IAEvB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC;AAND,sCAMC;AAED;;;;GAIG;AACH,SAAgB,UAAU,CAAC,OAAe;IACxC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;AAC3B,CAAC;AAFD,gCAEC;AAED;;;;;;GAMG;AACH,SAAgB,gBAAgB,CAAC,CAAS,EAAE,CAAS;IACnD,OAAO,CAAC,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;AAC7C,CAAC;AAFD,4CAEC;AAED;;;;;GAKG;AACH,SAAgB,WAAW,CAAC,GAAW;IACrC,6GAA6G;IAC7G,gFAAgF;IAChF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAC9B,OAAO,QAAQ,CAAC,QAAQ,EAAE,CAAC;AAC7B,CAAC;AALD,kCAKC","sourcesContent":["import type { Struct } from '@metamask/superstruct';\nimport { assert } from '@metamask/superstruct';\nimport type { Json } from '@metamask/utils';\n\n/**\n * Assert that a value is valid according to a struct.\n *\n * It is similar to superstruct's mask function, but it does not ignore extra\n * properties.\n *\n * @param value - Value to check.\n * @param struct - Struct to validate the value against.\n * @param message - Error message to throw if the value is not valid.\n * @returns The value if it is valid.\n */\nexport function strictMask<Type, Schema>(\n value: unknown,\n struct: Struct<Type, Schema>,\n message?: string,\n): Type {\n assert(value, struct, message);\n return value;\n}\n\n/**\n * Remove duplicate entries from an array.\n *\n * @param array - Array to remove duplicates from.\n * @returns Array with duplicates removed.\n */\nexport function unique<Type>(array: Type[] | Iterable<Type>): Type[] {\n return [...new Set(array)];\n}\n\n/**\n * Convert a value to a valid JSON object.\n *\n * The function chains JSON.stringify and JSON.parse to ensure that the result\n * is a valid JSON object. In objects, undefined values are removed, and in\n * arrays, they are replaced with null.\n *\n * @param value - Value to convert to JSON.\n * @returns JSON representation of the value.\n */\nexport function toJson<Type extends Json = Json>(value: any): Type {\n return JSON.parse(JSON.stringify(value)) as Type;\n}\n\n/**\n * Asserts that the given value is defined.\n *\n * @param value - Value to check.\n */\nexport function ensureDefined<Type>(\n value: Type | undefined,\n): asserts value is Type {\n if (value === undefined) {\n throw new Error('Argument is undefined');\n }\n}\n\n/**\n * Helper function that throws an error.\n *\n * @param message - Error message to throw.\n */\nexport function throwError(message: string): never {\n throw new Error(message);\n}\n\n/**\n * Compares two strings for equality, ignoring case.\n *\n * @param a - The first string to compare.\n * @param b - The second string to compare.\n * @returns `true` if the strings are equal, ignoring case. `false` otherwise.\n */\nexport function equalsIgnoreCase(a: string, b: string): boolean {\n return a.toLowerCase() === b.toLowerCase();\n}\n\n/**\n * Sanitize a URL.\n *\n * @param url - The URL to sanitize.\n * @returns The new sanitized redirect URL.\n */\nexport function sanitizeUrl(url: string): string {\n // For now, we only re-create the URL object which should take care of most of the sanitizing, like replacing\n // upper-cased letters by their lower-cased counterparts in the \"hostname\" part.\n const saferUrl = new URL(url);\n return saferUrl.toString();\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/eth-snap-keyring",
3
- "version": "4.3.3-38c4bd5",
3
+ "version": "4.3.6-d5a036e",
4
4
  "description": "Snaps keyring bridge.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -27,29 +27,30 @@
27
27
  "dependencies": {
28
28
  "@ethereumjs/tx": "^4.2.0",
29
29
  "@metamask/eth-sig-util": "^7.0.3",
30
- "@metamask/keyring-api": "^8.1.0",
31
- "@metamask/snaps-controllers": "^9.6.0",
32
- "@metamask/snaps-sdk": "^6.4.0",
33
- "@metamask/snaps-utils": "^7.8.0",
30
+ "@metamask/keyring-api": "^8.1.3",
31
+ "@metamask/snaps-controllers": "^9.10.0",
32
+ "@metamask/snaps-sdk": "^6.7.0",
33
+ "@metamask/snaps-utils": "^8.3.0",
34
34
  "@metamask/superstruct": "^3.1.0",
35
- "@metamask/utils": "^9.1.0",
36
- "@types/uuid": "^9.0.1",
37
- "deepmerge": "^4.2.2",
38
- "uuid": "^9.0.0"
35
+ "@metamask/utils": "^9.2.1",
36
+ "@types/uuid": "^9.0.8",
37
+ "uuid": "^9.0.1"
39
38
  },
40
39
  "devDependencies": {
41
- "@lavamoat/allow-scripts": "^3.0.4",
40
+ "@lavamoat/allow-scripts": "^3.2.1",
41
+ "@lavamoat/preinstall-always-fail": "^2.1.0",
42
42
  "@metamask/auto-changelog": "^3.4.4",
43
- "@types/jest": "^28.1.6",
44
- "@types/node": "^17.0.23",
45
- "depcheck": "^1.4.3",
46
- "jest": "^28.1.3",
47
- "jest-it-up": "^2.0.2",
48
- "rimraf": "^3.0.2",
49
- "ts-jest": "^28.0.7",
50
- "ts-node": "^10.7.0",
51
- "typedoc": "^0.23.15",
52
- "typescript": "~4.8.4"
43
+ "@types/jest": "^29.5.12",
44
+ "@types/node": "^20.12.12",
45
+ "deepmerge": "^4.2.2",
46
+ "depcheck": "^1.4.7",
47
+ "jest": "^29.5.0",
48
+ "jest-it-up": "^3.1.0",
49
+ "rimraf": "^5.0.10",
50
+ "ts-jest": "^29.0.5",
51
+ "ts-node": "^10.9.2",
52
+ "typedoc": "^0.25.13",
53
+ "typescript": "~5.4.5"
53
54
  },
54
55
  "engines": {
55
56
  "node": "^18.18 || >=20"