@metamask-previews/eth-snap-keyring 9.0.0-9c70d70 → 10.0.0-41bce29
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 +39 -1
- package/dist/SnapIdMap.cjs +11 -0
- package/dist/SnapIdMap.cjs.map +1 -1
- package/dist/SnapIdMap.d.cts +7 -0
- package/dist/SnapIdMap.d.cts.map +1 -1
- package/dist/SnapIdMap.d.mts +7 -0
- package/dist/SnapIdMap.d.mts.map +1 -1
- package/dist/SnapIdMap.mjs +11 -0
- package/dist/SnapIdMap.mjs.map +1 -1
- package/dist/SnapKeyring.cjs +182 -62
- package/dist/SnapKeyring.cjs.map +1 -1
- package/dist/SnapKeyring.d.cts +38 -2
- package/dist/SnapKeyring.d.cts.map +1 -1
- package/dist/SnapKeyring.d.mts +38 -2
- package/dist/SnapKeyring.d.mts.map +1 -1
- package/dist/SnapKeyring.mjs +182 -62
- package/dist/SnapKeyring.mjs.map +1 -1
- package/dist/SnapKeyringMessenger.cjs.map +1 -1
- package/dist/SnapKeyringMessenger.d.cts +2 -2
- package/dist/SnapKeyringMessenger.d.cts.map +1 -1
- package/dist/SnapKeyringMessenger.d.mts +2 -2
- package/dist/SnapKeyringMessenger.d.mts.map +1 -1
- package/dist/SnapKeyringMessenger.mjs.map +1 -1
- package/dist/logger.cjs +1 -1
- package/dist/logger.cjs.map +1 -1
- package/dist/logger.mjs +1 -1
- package/dist/logger.mjs.map +1 -1
- package/dist/migrations/v1.cjs +0 -4
- package/dist/migrations/v1.cjs.map +1 -1
- package/dist/migrations/v1.d.cts +1 -2
- package/dist/migrations/v1.d.cts.map +1 -1
- package/dist/migrations/v1.d.mts +1 -2
- package/dist/migrations/v1.d.mts.map +1 -1
- package/dist/migrations/v1.mjs +1 -5
- package/dist/migrations/v1.mjs.map +1 -1
- package/package.json +10 -10
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [10.0.0]
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **BREAKING:** Use `CaipAccountId` for `ResolvedAccountAddress.address` ([#186](https://github.com/MetaMask/accounts/pull/186))
|
|
15
|
+
- This was missing from SIP-26, but we expect this address to be CAIP-10 compliant.
|
|
16
|
+
- Bump `@metamask/keyring-api` from `^16.1.0` to `^17.0.0` ([#192](https://github.com/MetaMask/accounts/pull/192))
|
|
17
|
+
- Rename `ControllerMessenger` to `Messenger` ([#185](https://github.com/MetaMask/accounts/pull/185))
|
|
18
|
+
- Bump `@metamask/snaps-controllers` dependency from `^9.10.0` to `^9.18.0` ([#177](https://github.com/MetaMask/accounts/pull/177))
|
|
19
|
+
- Bump `@metamask/snaps-sdk` dependency from `^6.7.0` to `^6.16.0` ([#177](https://github.com/MetaMask/accounts/pull/177))
|
|
20
|
+
- Bump `@metamask/snaps-utils` dependency from `^8.3.0` to `^8.9.1` ([#177](https://github.com/MetaMask/accounts/pull/177))
|
|
21
|
+
|
|
22
|
+
## [9.1.1]
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Bump `@metamask/keyring-api` from `^16.0.0` to `^16.1.0` ([#176](https://github.com/MetaMask/accounts/pull/176))
|
|
27
|
+
|
|
28
|
+
## [9.1.0]
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- Add `submitRequest` and `resolveAccountAddress` methods ([#157](https://github.com/MetaMask/accounts/pull/157))
|
|
33
|
+
- Those new methods are required by the new signing request routing system (see SIP-26).
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- Bump `@metamask/keyring-api` from `^15.0.0` to `^16.0.0` ([#172](https://github.com/MetaMask/accounts/pull/172))
|
|
38
|
+
- Bump `@metamask/utils` from `^11.0.1` to `^11.1.0` ([#167](https://github.com/MetaMask/accounts/pull/167))
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- Fix async Snap request leak ([#171](https://github.com/MetaMask/accounts/pull/171))
|
|
43
|
+
- There was a leak with the deferred promises when an asynchronous request was not allowed.
|
|
44
|
+
|
|
10
45
|
## [9.0.0]
|
|
11
46
|
|
|
12
47
|
### Added
|
|
@@ -429,7 +464,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
429
464
|
|
|
430
465
|
- Initial release.
|
|
431
466
|
|
|
432
|
-
[Unreleased]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@
|
|
467
|
+
[Unreleased]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@10.0.0...HEAD
|
|
468
|
+
[10.0.0]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@9.1.1...@metamask/eth-snap-keyring@10.0.0
|
|
469
|
+
[9.1.1]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@9.1.0...@metamask/eth-snap-keyring@9.1.1
|
|
470
|
+
[9.1.0]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@9.0.0...@metamask/eth-snap-keyring@9.1.0
|
|
433
471
|
[9.0.0]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@8.1.1...@metamask/eth-snap-keyring@9.0.0
|
|
434
472
|
[8.1.1]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@8.1.0...@metamask/eth-snap-keyring@8.1.1
|
|
435
473
|
[8.1.0]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@8.0.0...@metamask/eth-snap-keyring@8.1.0
|
package/dist/SnapIdMap.cjs
CHANGED
|
@@ -151,6 +151,17 @@ class SnapIdMap {
|
|
|
151
151
|
has(snapId, key) {
|
|
152
152
|
return this.get(snapId, key) !== undefined;
|
|
153
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* Checks if a snap ID exists in the map.
|
|
156
|
+
*
|
|
157
|
+
* @param snapId - Snap ID present in the value to check.
|
|
158
|
+
* @returns `true` if the snap ID is present in the map, `false` otherwise.
|
|
159
|
+
*/
|
|
160
|
+
hasSnapId(snapId) {
|
|
161
|
+
// We could use a reverse-mapping to map Snap ID to their actual key too, but
|
|
162
|
+
// for now, this will do the trick.
|
|
163
|
+
return [...__classPrivateFieldGet(this, _SnapIdMap_map, "f").values()].some((value) => value.snapId === snapId);
|
|
164
|
+
}
|
|
154
165
|
/**
|
|
155
166
|
* Deletes a key from the map.
|
|
156
167
|
*
|
package/dist/SnapIdMap.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SnapIdMap.cjs","sourceRoot":"","sources":["../src/SnapIdMap.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAEA,iEAA0D;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;
|
|
1
|
+
{"version":3,"file":"SnapIdMap.cjs","sourceRoot":"","sources":["../src/SnapIdMap.ts"],"names":[],"mappings":"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","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 * Checks if a snap ID exists in the map.\n *\n * @param snapId - Snap ID present in the value to check.\n * @returns `true` if the snap ID is present in the map, `false` otherwise.\n */\n hasSnapId(snapId: SnapId): boolean {\n // We could use a reverse-mapping to map Snap ID to their actual key too, but\n // for now, this will do the trick.\n return [...this.#map.values()].some((value) => value.snapId === snapId);\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"]}
|
package/dist/SnapIdMap.d.cts
CHANGED
|
@@ -131,6 +131,13 @@ export declare class SnapIdMap<Value extends {
|
|
|
131
131
|
* value is equal to the given Snap ID, `false` otherwise.
|
|
132
132
|
*/
|
|
133
133
|
has(snapId: SnapId, key: string): boolean;
|
|
134
|
+
/**
|
|
135
|
+
* Checks if a snap ID exists in the map.
|
|
136
|
+
*
|
|
137
|
+
* @param snapId - Snap ID present in the value to check.
|
|
138
|
+
* @returns `true` if the snap ID is present in the map, `false` otherwise.
|
|
139
|
+
*/
|
|
140
|
+
hasSnapId(snapId: SnapId): boolean;
|
|
134
141
|
/**
|
|
135
142
|
* Deletes a key from the map.
|
|
136
143
|
*
|
package/dist/SnapIdMap.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SnapIdMap.d.cts","sourceRoot":"","sources":["../src/SnapIdMap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,4BAA4B;AAIlD;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;;;OAKG;gBACS,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;CAMxC;AAED;;;;;;GAMG;AACH,qBAAa,SAAS,CAAC,KAAK,SAAS;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE;;IAGrD;;;;;;;;;;;;;;;OAeG;gBACS,QAAQ,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAIzD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IAIjC;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,UAAU,CAAC,KAAK,SAAS;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,EAChD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GACzB,SAAS,CAAC,KAAK,CAAC;IAInB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAKnD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzC;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IAK5C;;;;;;;;;;;;;;;;;OAiBG;IAEH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAWpC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM,IAAI,gBAAgB,CAAC,KAAK,CAAC;IAIjC;;;;OAIG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
|
1
|
+
{"version":3,"file":"SnapIdMap.d.cts","sourceRoot":"","sources":["../src/SnapIdMap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,4BAA4B;AAIlD;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;;;OAKG;gBACS,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;CAMxC;AAED;;;;;;GAMG;AACH,qBAAa,SAAS,CAAC,KAAK,SAAS;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE;;IAGrD;;;;;;;;;;;;;;;OAeG;gBACS,QAAQ,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAIzD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IAIjC;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,UAAU,CAAC,KAAK,SAAS;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,EAChD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GACzB,SAAS,CAAC,KAAK,CAAC;IAInB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAKnD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzC;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAMlC;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IAK5C;;;;;;;;;;;;;;;;;OAiBG;IAEH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAWpC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM,IAAI,gBAAgB,CAAC,KAAK,CAAC;IAIjC;;;;OAIG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
package/dist/SnapIdMap.d.mts
CHANGED
|
@@ -131,6 +131,13 @@ export declare class SnapIdMap<Value extends {
|
|
|
131
131
|
* value is equal to the given Snap ID, `false` otherwise.
|
|
132
132
|
*/
|
|
133
133
|
has(snapId: SnapId, key: string): boolean;
|
|
134
|
+
/**
|
|
135
|
+
* Checks if a snap ID exists in the map.
|
|
136
|
+
*
|
|
137
|
+
* @param snapId - Snap ID present in the value to check.
|
|
138
|
+
* @returns `true` if the snap ID is present in the map, `false` otherwise.
|
|
139
|
+
*/
|
|
140
|
+
hasSnapId(snapId: SnapId): boolean;
|
|
134
141
|
/**
|
|
135
142
|
* Deletes a key from the map.
|
|
136
143
|
*
|
package/dist/SnapIdMap.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SnapIdMap.d.mts","sourceRoot":"","sources":["../src/SnapIdMap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,4BAA4B;AAIlD;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;;;OAKG;gBACS,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;CAMxC;AAED;;;;;;GAMG;AACH,qBAAa,SAAS,CAAC,KAAK,SAAS;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE;;IAGrD;;;;;;;;;;;;;;;OAeG;gBACS,QAAQ,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAIzD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IAIjC;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,UAAU,CAAC,KAAK,SAAS;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,EAChD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GACzB,SAAS,CAAC,KAAK,CAAC;IAInB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAKnD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzC;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IAK5C;;;;;;;;;;;;;;;;;OAiBG;IAEH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAWpC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM,IAAI,gBAAgB,CAAC,KAAK,CAAC;IAIjC;;;;OAIG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
|
1
|
+
{"version":3,"file":"SnapIdMap.d.mts","sourceRoot":"","sources":["../src/SnapIdMap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,4BAA4B;AAIlD;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;;;OAKG;gBACS,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;CAMxC;AAED;;;;;;GAMG;AACH,qBAAa,SAAS,CAAC,KAAK,SAAS;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE;;IAGrD;;;;;;;;;;;;;;;OAeG;gBACS,QAAQ,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAIzD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IAIjC;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,UAAU,CAAC,KAAK,SAAS;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,EAChD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GACzB,SAAS,CAAC,KAAK,CAAC;IAInB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAKnD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzC;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAMlC;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IAK5C;;;;;;;;;;;;;;;;;OAiBG;IAEH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAWpC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM,IAAI,gBAAgB,CAAC,KAAK,CAAC;IAIjC;;;;OAIG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
package/dist/SnapIdMap.mjs
CHANGED
|
@@ -147,6 +147,17 @@ export class SnapIdMap {
|
|
|
147
147
|
has(snapId, key) {
|
|
148
148
|
return this.get(snapId, key) !== undefined;
|
|
149
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* Checks if a snap ID exists in the map.
|
|
152
|
+
*
|
|
153
|
+
* @param snapId - Snap ID present in the value to check.
|
|
154
|
+
* @returns `true` if the snap ID is present in the map, `false` otherwise.
|
|
155
|
+
*/
|
|
156
|
+
hasSnapId(snapId) {
|
|
157
|
+
// We could use a reverse-mapping to map Snap ID to their actual key too, but
|
|
158
|
+
// for now, this will do the trick.
|
|
159
|
+
return [...__classPrivateFieldGet(this, _SnapIdMap_map, "f").values()].some((value) => value.snapId === snapId);
|
|
160
|
+
}
|
|
150
161
|
/**
|
|
151
162
|
* Deletes a key from the map.
|
|
152
163
|
*
|
package/dist/SnapIdMap.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SnapIdMap.mjs","sourceRoot":"","sources":["../src/SnapIdMap.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,OAAO,EAAE,kBAAkB,EAAE,iCAA6B;AAE1D;;GAEG;AACH,MAAM,OAAO,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;AAED;;;;;;GAMG;AACH,MAAM,OAAO,SAAS;IAGpB;;;;;;;;;;;;;;;OAeG;IACH,YAAY,QAA6C;QAlBhD,iCAAgC;QAmBvC,uBAAA,IAAI,kBAAQ,IAAI,kBAAkB,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","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"]}
|
|
1
|
+
{"version":3,"file":"SnapIdMap.mjs","sourceRoot":"","sources":["../src/SnapIdMap.ts"],"names":[],"mappings":"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","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 * Checks if a snap ID exists in the map.\n *\n * @param snapId - Snap ID present in the value to check.\n * @returns `true` if the snap ID is present in the map, `false` otherwise.\n */\n hasSnapId(snapId: SnapId): boolean {\n // We could use a reverse-mapping to map Snap ID to their actual key too, but\n // for now, this will do the trick.\n return [...this.#map.values()].some((value) => value.snapId === snapId);\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"]}
|
package/dist/SnapKeyring.cjs
CHANGED
|
@@ -13,7 +13,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
13
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");
|
|
14
14
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
15
15
|
};
|
|
16
|
-
var _SnapKeyring_instances, _SnapKeyring_messenger, _SnapKeyring_snapClient, _SnapKeyring_accounts, _SnapKeyring_requests, _SnapKeyring_callbacks, _SnapKeyring_handleAccountCreated, _SnapKeyring_handleAccountUpdated, _SnapKeyring_handleAccountDeleted, _SnapKeyring_handleRequestApproved, _SnapKeyring_handleRequestRejected, _SnapKeyring_rePublishAccountEvent, _SnapKeyring_handleAccountBalancesUpdated, _SnapKeyring_handleAccountAssetListUpdated, _SnapKeyring_handleAccountTransactionsUpdated, _SnapKeyring_submitRequest, _SnapKeyring_hasMethod, _SnapKeyring_createRequestPromise,
|
|
16
|
+
var _SnapKeyring_instances, _SnapKeyring_messenger, _SnapKeyring_snapClient, _SnapKeyring_accounts, _SnapKeyring_requests, _SnapKeyring_callbacks, _SnapKeyring_handleAccountCreated, _SnapKeyring_handleAccountUpdated, _SnapKeyring_handleAccountDeleted, _SnapKeyring_handleRequestApproved, _SnapKeyring_handleRequestRejected, _SnapKeyring_rePublishAccountEvent, _SnapKeyring_handleAccountBalancesUpdated, _SnapKeyring_handleAccountAssetListUpdated, _SnapKeyring_handleAccountTransactionsUpdated, _SnapKeyring_getAccount, _SnapKeyring_submitRequest, _SnapKeyring_submitSnapRequest, _SnapKeyring_hasMethod, _SnapKeyring_createRequestPromise, _SnapKeyring_clearRequestPromise, _SnapKeyring_handleSyncResponse, _SnapKeyring_handleAsyncResponse, _SnapKeyring_sanitizeRedirectUrl, _SnapKeyring_validateRedirectUrl, _SnapKeyring_deleteAccount, _SnapKeyring_resolveAddress, _SnapKeyring_getSnap, _SnapKeyring_getSnapMetadata, _SnapKeyring_getSnapAllowedOrigins;
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.SnapKeyring = exports.SNAP_KEYRING_TYPE = void 0;
|
|
19
19
|
const tx_1 = require("@ethereumjs/tx");
|
|
@@ -189,6 +189,58 @@ class SnapKeyring extends events_1.EventEmitter {
|
|
|
189
189
|
.filter(({ snapId: accountSnapId }) => accountSnapId === snapId)
|
|
190
190
|
.map(({ account }) => normalizeAccountAddress(account)));
|
|
191
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* Checks if a Snap ID is known from the keyring.
|
|
194
|
+
*
|
|
195
|
+
* @param snapId - Snap ID.
|
|
196
|
+
* @returns `true` if the Snap ID is known, `false` otherwise.
|
|
197
|
+
*/
|
|
198
|
+
hasSnapId(snapId) {
|
|
199
|
+
return __classPrivateFieldGet(this, _SnapKeyring_accounts, "f").hasSnapId(snapId);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Resolve the Snap account's address associated from a signing request.
|
|
203
|
+
*
|
|
204
|
+
* @param snapId - Snap ID.
|
|
205
|
+
* @param scope - CAIP-2 chain ID.
|
|
206
|
+
* @param request - Signing request object.
|
|
207
|
+
* @throws An error if the Snap ID is not known from the keyring.
|
|
208
|
+
* @returns The resolved address if found, `null` otherwise.
|
|
209
|
+
*/
|
|
210
|
+
async resolveAccountAddress(snapId, scope, request) {
|
|
211
|
+
// We do check that the incoming Snap ID is known by the keyring.
|
|
212
|
+
if (!this.hasSnapId(snapId)) {
|
|
213
|
+
throw new Error(`Unable to resolve account address: unknown Snap ID: ${snapId}`);
|
|
214
|
+
}
|
|
215
|
+
return await __classPrivateFieldGet(this, _SnapKeyring_snapClient, "f")
|
|
216
|
+
.withSnapId(snapId)
|
|
217
|
+
.resolveAccountAddress(scope, request);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Submit a request to a Snap from an account ID.
|
|
221
|
+
*
|
|
222
|
+
* This request cannot be an asynchronous keyring request.
|
|
223
|
+
*
|
|
224
|
+
* @param opts - Request options.
|
|
225
|
+
* @param opts.account - Account ID.
|
|
226
|
+
* @param opts.method - Method to call.
|
|
227
|
+
* @param opts.params - Method parameters.
|
|
228
|
+
* @param opts.scope - Selected chain ID (CAIP-2).
|
|
229
|
+
* @returns Promise that resolves to the result of the method call.
|
|
230
|
+
*/
|
|
231
|
+
async submitRequest({ account: accountId, method, params, scope, }) {
|
|
232
|
+
const { account, snapId } = __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_getAccount).call(this, accountId);
|
|
233
|
+
return await __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_submitSnapRequest).call(this, {
|
|
234
|
+
snapId,
|
|
235
|
+
account,
|
|
236
|
+
method: method,
|
|
237
|
+
params,
|
|
238
|
+
scope,
|
|
239
|
+
// For non-EVM (in the context of the multichain API and SIP-26), we enforce responses
|
|
240
|
+
// to be synchronous.
|
|
241
|
+
noPending: true,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
192
244
|
/**
|
|
193
245
|
* Sign a transaction.
|
|
194
246
|
*
|
|
@@ -209,7 +261,7 @@ class SnapKeyring extends events_1.EventEmitter {
|
|
|
209
261
|
address,
|
|
210
262
|
method: keyring_api_1.EthMethod.SignTransaction,
|
|
211
263
|
params: [tx],
|
|
212
|
-
|
|
264
|
+
scope: (0, utils_1.toCaipChainId)(utils_1.KnownCaipNamespace.Eip155, `${chainId}`),
|
|
213
265
|
});
|
|
214
266
|
// ! It's *** CRITICAL *** that we mask the signature here, otherwise the
|
|
215
267
|
// ! Snap could overwrite the transaction.
|
|
@@ -252,7 +304,7 @@ class SnapKeyring extends events_1.EventEmitter {
|
|
|
252
304
|
...(chainId === undefined
|
|
253
305
|
? {}
|
|
254
306
|
: {
|
|
255
|
-
|
|
307
|
+
scope: (0, utils_1.toCaipChainId)(utils_1.KnownCaipNamespace.Eip155, `${chainId}`),
|
|
256
308
|
}),
|
|
257
309
|
}), keyring_api_1.EthBytesStruct);
|
|
258
310
|
}
|
|
@@ -302,7 +354,7 @@ class SnapKeyring extends events_1.EventEmitter {
|
|
|
302
354
|
params: (0, util_1.toJson)(transactions),
|
|
303
355
|
noPending: true,
|
|
304
356
|
// We assume the chain ID is already well formatted
|
|
305
|
-
|
|
357
|
+
scope: (0, utils_1.toCaipChainId)(utils_1.KnownCaipNamespace.Eip155, context.chainId),
|
|
306
358
|
}), keyring_api_1.EthBaseUserOperationStruct);
|
|
307
359
|
}
|
|
308
360
|
/**
|
|
@@ -321,7 +373,7 @@ class SnapKeyring extends events_1.EventEmitter {
|
|
|
321
373
|
params: (0, util_1.toJson)([userOp]),
|
|
322
374
|
noPending: true,
|
|
323
375
|
// We assume the chain ID is already well formatted
|
|
324
|
-
|
|
376
|
+
scope: (0, utils_1.toCaipChainId)(utils_1.KnownCaipNamespace.Eip155, context.chainId),
|
|
325
377
|
}), keyring_api_1.EthUserOperationPatchStruct);
|
|
326
378
|
}
|
|
327
379
|
/**
|
|
@@ -338,7 +390,7 @@ class SnapKeyring extends events_1.EventEmitter {
|
|
|
338
390
|
method: keyring_api_1.EthMethod.SignUserOperation,
|
|
339
391
|
params: (0, util_1.toJson)([userOp]),
|
|
340
392
|
// We assume the chain ID is already well formatted
|
|
341
|
-
|
|
393
|
+
scope: (0, utils_1.toCaipChainId)(utils_1.KnownCaipNamespace.Eip155, context.chainId),
|
|
342
394
|
}), keyring_api_1.EthBytesStruct);
|
|
343
395
|
}
|
|
344
396
|
/**
|
|
@@ -362,18 +414,7 @@ class SnapKeyring extends events_1.EventEmitter {
|
|
|
362
414
|
*/
|
|
363
415
|
async removeAccount(address) {
|
|
364
416
|
const { account, snapId } = __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_resolveAddress).call(this, address);
|
|
365
|
-
|
|
366
|
-
// fail to delete it.
|
|
367
|
-
__classPrivateFieldGet(this, _SnapKeyring_accounts, "f").delete(snapId, account.id);
|
|
368
|
-
try {
|
|
369
|
-
await __classPrivateFieldGet(this, _SnapKeyring_snapClient, "f").withSnapId(snapId).deleteAccount(account.id);
|
|
370
|
-
}
|
|
371
|
-
catch (error) {
|
|
372
|
-
// If the Snap failed to delete the account, log the error and continue
|
|
373
|
-
// with the account deletion, otherwise the account will be stuck in the
|
|
374
|
-
// keyring.
|
|
375
|
-
console.error(`Account '${address}' may not have been removed from snap '${snapId}':`, error);
|
|
376
|
-
}
|
|
417
|
+
await __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_deleteAccount).call(this, snapId, account);
|
|
377
418
|
}
|
|
378
419
|
/**
|
|
379
420
|
* Return an internal account object for a given address.
|
|
@@ -429,6 +470,10 @@ _SnapKeyring_messenger = new WeakMap(), _SnapKeyring_snapClient = new WeakMap(),
|
|
|
429
470
|
async function _SnapKeyring_handleAccountCreated(snapId, message) {
|
|
430
471
|
(0, superstruct_1.assert)(message, events_2.AccountCreatedEventStruct);
|
|
431
472
|
const { account: newAccountFromEvent, accountNameSuggestion, displayConfirmation, } = message.params;
|
|
473
|
+
// READ THIS CAREFULLY:
|
|
474
|
+
// ------------------------------------------------------------------------
|
|
475
|
+
// The account creation flow is now asynchronous. We expect the Snap to
|
|
476
|
+
// first create the account data and then fire the "AccountCreated" event.
|
|
432
477
|
// Potentially migrate the account.
|
|
433
478
|
const account = (0, account_1.transformAccount)(newAccountFromEvent);
|
|
434
479
|
// The UI still uses the account address to identify accounts, so we need
|
|
@@ -443,12 +488,55 @@ async function _SnapKeyring_handleAccountCreated(snapId, message) {
|
|
|
443
488
|
if (__classPrivateFieldGet(this, _SnapKeyring_accounts, "f").has(snapId, account.id)) {
|
|
444
489
|
throw new Error(`Account '${account.id}' already exists`);
|
|
445
490
|
}
|
|
446
|
-
|
|
491
|
+
// A deferred promise that will be resolved once the Snap keyring has saved
|
|
492
|
+
// its internal state.
|
|
493
|
+
// This part of the flow is run asynchronously, so we have no other way of
|
|
494
|
+
// letting the MetaMask client that this "save" has been run.
|
|
495
|
+
// NOTE: Another way of fixing that could be to rely on events through the
|
|
496
|
+
// messenger maybe?
|
|
497
|
+
const onceSaved = new DeferredPromise_1.DeferredPromise();
|
|
498
|
+
// Add the account to the keyring, but wait for the MetaMask client to
|
|
499
|
+
// approve the account creation first.
|
|
500
|
+
await __classPrivateFieldGet(this, _SnapKeyring_callbacks, "f").addAccount(address, snapId,
|
|
501
|
+
// This callback is passed to the MetaMask client, it will be called whenever
|
|
502
|
+
// the end user will accept or not the account creation.
|
|
503
|
+
async (accepted) => {
|
|
447
504
|
if (accepted) {
|
|
505
|
+
// We consider the account to be created on the Snap keyring only if
|
|
506
|
+
// the user accepted it. Meaning that the Snap MIGHT HAVE created the
|
|
507
|
+
// account on its own state, but the Snap keyring MIGHT NOT HAVE it yet.
|
|
508
|
+
//
|
|
509
|
+
// e.g The account creation dialog crashed on MetaMask, this callback
|
|
510
|
+
// will never be called, but the Snap still has the account.
|
|
448
511
|
__classPrivateFieldGet(this, _SnapKeyring_accounts, "f").set(account.id, { account, snapId });
|
|
449
|
-
await
|
|
512
|
+
// This is the "true async part". We do not `await` for this call, mainly
|
|
513
|
+
// because this callback will persist the account on the client side
|
|
514
|
+
// (through the `AccountsController`).
|
|
515
|
+
//
|
|
516
|
+
// Since this will happen after the Snap account creation and Snap
|
|
517
|
+
// event, if anything goes wrong, we will delete the account by
|
|
518
|
+
// calling `deleteAccount` on the Snap.
|
|
519
|
+
// eslint-disable-next-line no-void
|
|
520
|
+
void __classPrivateFieldGet(this, _SnapKeyring_callbacks, "f")
|
|
521
|
+
.saveState()
|
|
522
|
+
.then(() => {
|
|
523
|
+
// This allows the MetaMask client to be "notified" when then
|
|
524
|
+
// Snap keyring has truly persisted its state. From there, we should
|
|
525
|
+
// be able to use the account (e.g. to display account creation
|
|
526
|
+
// confirmation dialogs).
|
|
527
|
+
onceSaved.resolve(account.id);
|
|
528
|
+
})
|
|
529
|
+
.catch(async (error) => {
|
|
530
|
+
// FIXME: There's a potential race condition here, if the Snap did
|
|
531
|
+
// not persist the account yet (this should mostly be for older Snaps).
|
|
532
|
+
await __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_deleteAccount).call(this, snapId, account);
|
|
533
|
+
// This allows the MetaMask client to be "notified" that something went
|
|
534
|
+
// wrong with the Snap keyring. (e.g. useful to display account creation
|
|
535
|
+
// error dialogs).
|
|
536
|
+
onceSaved.reject(error);
|
|
537
|
+
});
|
|
450
538
|
}
|
|
451
|
-
}, accountNameSuggestion, displayConfirmation);
|
|
539
|
+
}, onceSaved.promise, accountNameSuggestion, displayConfirmation);
|
|
452
540
|
return null;
|
|
453
541
|
}, _SnapKeyring_handleAccountUpdated =
|
|
454
542
|
/**
|
|
@@ -576,76 +664,61 @@ async function _SnapKeyring_handleAccountAssetListUpdated(message) {
|
|
|
576
664
|
async function _SnapKeyring_handleAccountTransactionsUpdated(message) {
|
|
577
665
|
(0, superstruct_1.assert)(message, keyring_api_1.AccountTransactionsUpdatedEventStruct);
|
|
578
666
|
return __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_rePublishAccountEvent).call(this, 'SnapKeyring:accountTransactionsUpdated', message.params);
|
|
667
|
+
}, _SnapKeyring_getAccount = function _SnapKeyring_getAccount(id) {
|
|
668
|
+
const found = [...__classPrivateFieldGet(this, _SnapKeyring_accounts, "f").values()].find((entry) => entry.account.id === id);
|
|
669
|
+
if (!found) {
|
|
670
|
+
throw new Error(`Unable to get account: unknown account ID: '${id}'`);
|
|
671
|
+
}
|
|
672
|
+
return found;
|
|
579
673
|
}, _SnapKeyring_submitRequest =
|
|
580
674
|
/**
|
|
581
|
-
* Submit a request to a Snap.
|
|
675
|
+
* Submit a request to a Snap from an account address.
|
|
582
676
|
*
|
|
583
677
|
* @param opts - Request options.
|
|
584
678
|
* @param opts.address - Account address.
|
|
585
679
|
* @param opts.method - Method to call.
|
|
586
680
|
* @param opts.params - Method parameters.
|
|
587
|
-
* @param opts.
|
|
681
|
+
* @param opts.scope - Selected chain ID (CAIP-2).
|
|
588
682
|
* @param opts.noPending - Whether the response is allowed to be pending.
|
|
589
683
|
* @returns Promise that resolves to the result of the method call.
|
|
590
684
|
*/
|
|
591
|
-
async function _SnapKeyring_submitRequest({ address, method, params,
|
|
685
|
+
async function _SnapKeyring_submitRequest({ address, method, params, scope = '', noPending = false, }) {
|
|
592
686
|
const { account, snapId } = __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_resolveAddress).call(this, address);
|
|
593
|
-
|
|
594
|
-
throw new Error(`Method '${method}' not supported for account ${account.address}`);
|
|
595
|
-
}
|
|
596
|
-
const requestId = (0, uuid_1.v4)();
|
|
597
|
-
// Create the promise before calling the Snap to prevent a race condition
|
|
598
|
-
// where the Snap responds before we have a chance to create it.
|
|
599
|
-
const promise = __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_createRequestPromise).call(this, requestId, snapId);
|
|
600
|
-
const response = await __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_submitSnapRequest).call(this, {
|
|
687
|
+
return await __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_submitSnapRequest).call(this, {
|
|
601
688
|
snapId,
|
|
602
|
-
requestId,
|
|
603
689
|
account,
|
|
604
690
|
method: method,
|
|
605
691
|
params,
|
|
606
|
-
|
|
692
|
+
scope,
|
|
693
|
+
noPending,
|
|
607
694
|
});
|
|
608
|
-
// Some methods, like the ones used to prepare and patch user operations,
|
|
609
|
-
// require the Snap to answer synchronously in order to work with the
|
|
610
|
-
// confirmation flow. This check lets the caller enforce this behavior.
|
|
611
|
-
if (noPending && response.pending) {
|
|
612
|
-
throw new Error(`Request '${requestId}' to snap '${snapId}' is pending and noPending is true.`);
|
|
613
|
-
}
|
|
614
|
-
// If the Snap answers synchronously, the promise must be removed from the
|
|
615
|
-
// map to prevent a leak.
|
|
616
|
-
if (!response.pending) {
|
|
617
|
-
return __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_handleSyncResponse).call(this, response, requestId, snapId);
|
|
618
|
-
}
|
|
619
|
-
// If the Snap answers asynchronously, we will inform the user with a redirect
|
|
620
|
-
if (response.redirect?.message || response.redirect?.url) {
|
|
621
|
-
await __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_handleAsyncResponse).call(this, response.redirect, snapId);
|
|
622
|
-
}
|
|
623
|
-
return promise.promise;
|
|
624
|
-
}, _SnapKeyring_hasMethod = function _SnapKeyring_hasMethod(account, method) {
|
|
625
|
-
return account.methods.includes(method);
|
|
626
|
-
}, _SnapKeyring_createRequestPromise = function _SnapKeyring_createRequestPromise(requestId, snapId) {
|
|
627
|
-
const promise = new DeferredPromise_1.DeferredPromise();
|
|
628
|
-
__classPrivateFieldGet(this, _SnapKeyring_requests, "f").set(requestId, { promise, snapId });
|
|
629
|
-
return promise;
|
|
630
695
|
}, _SnapKeyring_submitSnapRequest =
|
|
631
696
|
/**
|
|
632
697
|
* Submits a request to a Snap.
|
|
633
698
|
*
|
|
634
699
|
* @param options - The options for the Snap request.
|
|
635
700
|
* @param options.snapId - The Snap ID to submit the request to.
|
|
636
|
-
* @param options.requestId - The unique identifier for the request.
|
|
637
701
|
* @param options.account - The account to use for the request.
|
|
638
702
|
* @param options.method - The Ethereum method to call.
|
|
639
703
|
* @param options.params - The parameters to pass to the method, can be undefined.
|
|
640
|
-
* @param options.
|
|
704
|
+
* @param options.scope - The chain ID to use for the request, can be an empty string.
|
|
705
|
+
* @param options.noPending - Whether the response is allowed to be pending.
|
|
641
706
|
* @returns A promise that resolves to the keyring response from the Snap.
|
|
642
707
|
* @throws An error if the Snap fails to respond or if there's an issue with the request submission.
|
|
643
708
|
*/
|
|
644
|
-
async function _SnapKeyring_submitSnapRequest({ snapId,
|
|
709
|
+
async function _SnapKeyring_submitSnapRequest({ snapId, account, method, params, scope, noPending, }) {
|
|
710
|
+
if (!__classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_hasMethod).call(this, account, method)) {
|
|
711
|
+
throw new Error(`Method '${method}' not supported for account ${account.address}`);
|
|
712
|
+
}
|
|
713
|
+
// Generate a new random request ID to keep track of the request execution flow.
|
|
714
|
+
const requestId = (0, uuid_1.v4)();
|
|
715
|
+
// Create the promise before calling the Snap to prevent a race condition
|
|
716
|
+
// where the Snap responds before we have a chance to create it.
|
|
717
|
+
const requestPromise = __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_createRequestPromise).call(this, requestId, snapId);
|
|
645
718
|
try {
|
|
646
719
|
const request = {
|
|
647
720
|
id: requestId,
|
|
648
|
-
scope
|
|
721
|
+
scope,
|
|
649
722
|
account: account.id,
|
|
650
723
|
request: {
|
|
651
724
|
method,
|
|
@@ -653,16 +726,43 @@ async function _SnapKeyring_submitSnapRequest({ snapId, requestId, account, meth
|
|
|
653
726
|
},
|
|
654
727
|
};
|
|
655
728
|
(0, logger_1.projectLogger)('Submit Snap request: ', request);
|
|
656
|
-
|
|
729
|
+
const response = await __classPrivateFieldGet(this, _SnapKeyring_snapClient, "f")
|
|
730
|
+
.withSnapId(snapId)
|
|
731
|
+
.submitRequest(request);
|
|
732
|
+
// Some methods, like the ones used to prepare and patch user operations,
|
|
733
|
+
// require the Snap to answer synchronously in order to work with the
|
|
734
|
+
// confirmation flow. This check lets the caller enforce this behavior.
|
|
735
|
+
if (noPending && response.pending) {
|
|
736
|
+
throw new Error(`Request '${requestId}' to Snap '${snapId}' is pending and noPending is true.`);
|
|
737
|
+
}
|
|
738
|
+
// If the Snap answers synchronously, the promise must be removed from the
|
|
739
|
+
// map to prevent a leak.
|
|
740
|
+
if (!response.pending) {
|
|
741
|
+
return __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_handleSyncResponse).call(this, response, requestId, snapId);
|
|
742
|
+
}
|
|
743
|
+
// If the Snap answers asynchronously, we will inform the user with a redirect
|
|
744
|
+
if (response.redirect?.message || response.redirect?.url) {
|
|
745
|
+
await __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_handleAsyncResponse).call(this, response.redirect, snapId);
|
|
746
|
+
}
|
|
747
|
+
return requestPromise.promise;
|
|
657
748
|
}
|
|
658
749
|
catch (error) {
|
|
659
750
|
(0, logger_1.projectLogger)('Snap Request failed: ', { requestId });
|
|
660
751
|
// If the Snap failed to respond, delete the promise to prevent a leak.
|
|
661
|
-
__classPrivateFieldGet(this,
|
|
752
|
+
__classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_clearRequestPromise).call(this, requestId, snapId);
|
|
662
753
|
throw error;
|
|
663
754
|
}
|
|
755
|
+
}, _SnapKeyring_hasMethod = function _SnapKeyring_hasMethod(account, method) {
|
|
756
|
+
return account.methods.includes(method);
|
|
757
|
+
}, _SnapKeyring_createRequestPromise = function _SnapKeyring_createRequestPromise(requestId, snapId) {
|
|
758
|
+
const promise = new DeferredPromise_1.DeferredPromise();
|
|
759
|
+
__classPrivateFieldGet(this, _SnapKeyring_requests, "f").set(requestId, { promise, snapId });
|
|
760
|
+
return promise;
|
|
761
|
+
}, _SnapKeyring_clearRequestPromise = function _SnapKeyring_clearRequestPromise(requestId, snapId) {
|
|
762
|
+
__classPrivateFieldGet(this, _SnapKeyring_requests, "f").delete(snapId, requestId);
|
|
664
763
|
}, _SnapKeyring_handleSyncResponse = function _SnapKeyring_handleSyncResponse(response, requestId, snapId) {
|
|
665
764
|
__classPrivateFieldGet(this, _SnapKeyring_requests, "f").delete(snapId, requestId);
|
|
765
|
+
// We consider `Response` to be compatible with `result` here.
|
|
666
766
|
return response.result;
|
|
667
767
|
}, _SnapKeyring_handleAsyncResponse =
|
|
668
768
|
/**
|
|
@@ -694,6 +794,26 @@ async function _SnapKeyring_handleAsyncResponse(redirect, snapId) {
|
|
|
694
794
|
if (!allowedOrigins.includes(origin)) {
|
|
695
795
|
throw new Error(`Redirect URL domain '${origin}' is not an allowed origin by snap '${snapId}'`);
|
|
696
796
|
}
|
|
797
|
+
}, _SnapKeyring_deleteAccount =
|
|
798
|
+
/**
|
|
799
|
+
* Removes an account.
|
|
800
|
+
*
|
|
801
|
+
* @param snapId - Snap ID.
|
|
802
|
+
* @param account - Account to delete.
|
|
803
|
+
*/
|
|
804
|
+
async function _SnapKeyring_deleteAccount(snapId, account) {
|
|
805
|
+
// Always remove the account from the maps, even if the Snap is going to
|
|
806
|
+
// fail to delete it.
|
|
807
|
+
__classPrivateFieldGet(this, _SnapKeyring_accounts, "f").delete(snapId, account.id);
|
|
808
|
+
try {
|
|
809
|
+
await __classPrivateFieldGet(this, _SnapKeyring_snapClient, "f").withSnapId(snapId).deleteAccount(account.id);
|
|
810
|
+
}
|
|
811
|
+
catch (error) {
|
|
812
|
+
// If the Snap failed to delete the account, log the error and continue
|
|
813
|
+
// with the account deletion, otherwise the account will be stuck in the
|
|
814
|
+
// keyring.
|
|
815
|
+
console.error(`Account '${account.address}' may not have been removed from snap '${snapId}':`, error);
|
|
816
|
+
}
|
|
697
817
|
}, _SnapKeyring_resolveAddress = function _SnapKeyring_resolveAddress(address) {
|
|
698
818
|
return ([...__classPrivateFieldGet(this, _SnapKeyring_accounts, "f").values()].find(({ account }) => (0, util_1.equalsIgnoreCase)(account.address, address)) ?? (0, util_1.throwError)(`Account '${address}' not found`));
|
|
699
819
|
}, _SnapKeyring_getSnap = function _SnapKeyring_getSnap(snapId) {
|