@metamask/snaps-utils
Advanced tools
Comparing version 2.0.1 to 3.0.0
@@ -9,2 +9,11 @@ # Changelog | ||
## [3.0.0] | ||
### Added | ||
- Add keyring export and endowment ([#1787](https://github.com/MetaMask/snaps/pull/1787)) | ||
- Add optional `allowedOrigins` field to `endowment:rpc` ([#1822](https://github.com/MetaMask/snaps/pull/1822)) | ||
- This can be used to only accept certain origins in your Snap. | ||
### Changed | ||
- **BREAKING:** Bump minimum Node.js version to `^18.16.0` ([#1741](https://github.com/MetaMask/snaps/pull/1741)) | ||
## [2.0.1] | ||
@@ -54,3 +63,4 @@ ### Changed | ||
[Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-utils@2.0.1...HEAD | ||
[Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-utils@3.0.0...HEAD | ||
[3.0.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-utils@2.0.1...@metamask/snaps-utils@3.0.0 | ||
[2.0.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-utils@2.0.0...@metamask/snaps-utils@2.0.1 | ||
@@ -57,0 +67,0 @@ [2.0.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-utils@0.38.4-flask.1...@metamask/snaps-utils@2.0.0 |
@@ -29,2 +29,5 @@ "use strict"; | ||
SnapCaveatType[/** | ||
* The origins that a Snap can receive keyring messages from. | ||
*/ "KeyringOrigin"] = 'keyringOrigin'; | ||
SnapCaveatType[/** | ||
* Caveat specifying the snap IDs that can be interacted with. | ||
@@ -31,0 +34,0 @@ */ "SnapIds"] = 'snapIds'; |
@@ -30,2 +30,3 @@ "use strict"; | ||
HandlerType["OnNameLookup"] = 'onNameLookup'; | ||
HandlerType["OnKeyringRequest"] = 'onKeyringRequest'; | ||
})(HandlerType || (HandlerType = {})); | ||
@@ -74,2 +75,9 @@ const SNAP_EXPORTS = { | ||
} | ||
}, | ||
[HandlerType.OnKeyringRequest]: { | ||
type: HandlerType.OnKeyringRequest, | ||
required: true, | ||
validator: (snapExport)=>{ | ||
return typeof snapExport === 'function'; | ||
} | ||
} | ||
@@ -76,0 +84,0 @@ }; |
@@ -18,2 +18,11 @@ "use strict"; | ||
}, | ||
KeyringOriginsStruct: function() { | ||
return KeyringOriginsStruct; | ||
}, | ||
assertIsKeyringOrigins: function() { | ||
return assertIsKeyringOrigins; | ||
}, | ||
isOriginAllowed: function() { | ||
return isOriginAllowed; | ||
}, | ||
assertIsJsonRpcSuccess: function() { | ||
@@ -23,2 +32,3 @@ return assertIsJsonRpcSuccess; | ||
}); | ||
const _permissioncontroller = require("@metamask/permission-controller"); | ||
const _utils = require("@metamask/utils"); | ||
@@ -28,8 +38,10 @@ const _superstruct = require("superstruct"); | ||
dapps: (0, _superstruct.optional)((0, _superstruct.boolean)()), | ||
snaps: (0, _superstruct.optional)((0, _superstruct.boolean)()) | ||
snaps: (0, _superstruct.optional)((0, _superstruct.boolean)()), | ||
allowedOrigins: (0, _superstruct.optional)((0, _superstruct.array)((0, _superstruct.string)())) | ||
}), 'RPC origins', (value)=>{ | ||
if (!Object.values(value).some(Boolean)) { | ||
throw new Error('Must specify at least one JSON-RPC origin'); | ||
const hasOrigins = Boolean(value.snaps === true || value.dapps === true || value.allowedOrigins && value.allowedOrigins.length > 0); | ||
if (hasOrigins) { | ||
return true; | ||
} | ||
return true; | ||
return 'Must specify at least one JSON-RPC origin.'; | ||
}); | ||
@@ -40,2 +52,25 @@ function assertIsRpcOrigins(value, // eslint-disable-next-line @typescript-eslint/naming-convention | ||
} | ||
const KeyringOriginsStruct = (0, _superstruct.object)({ | ||
allowedOrigins: (0, _superstruct.optional)((0, _superstruct.array)((0, _superstruct.string)())) | ||
}); | ||
function assertIsKeyringOrigins(value, // eslint-disable-next-line @typescript-eslint/naming-convention | ||
ErrorWrapper) { | ||
(0, _utils.assertStruct)(value, KeyringOriginsStruct, 'Invalid keyring origins', ErrorWrapper); | ||
} | ||
function isOriginAllowed(origins, subjectType, origin) { | ||
// The MetaMask client is always allowed. | ||
if (origin === 'metamask') { | ||
return true; | ||
} | ||
// If the origin is in the `allowedOrigins` list, it is allowed. | ||
if (origins.allowedOrigins?.includes(origin)) { | ||
return true; | ||
} | ||
// If the origin is a website and `dapps` is true, it is allowed. | ||
if (subjectType === _permissioncontroller.SubjectType.Website && origins.dapps) { | ||
return true; | ||
} | ||
// If the origin is a snap and `snaps` is true, it is allowed. | ||
return Boolean(subjectType === _permissioncontroller.SubjectType.Snap && origins.snaps); | ||
} | ||
function assertIsJsonRpcSuccess(value) { | ||
@@ -42,0 +77,0 @@ if (!(0, _utils.isJsonRpcSuccess)(value)) { |
@@ -137,2 +137,3 @@ "use strict"; | ||
'endowment:name-lookup': (0, _superstruct.optional)(ChainIdsStruct), | ||
'endowment:keyring': (0, _superstruct.optional)(_jsonrpc.KeyringOriginsStruct), | ||
snap_dialog: (0, _superstruct.optional)((0, _superstruct.object)({})), | ||
@@ -139,0 +140,0 @@ // TODO: Remove |
@@ -19,2 +19,5 @@ export var SnapCaveatType; | ||
SnapCaveatType[/** | ||
* The origins that a Snap can receive keyring messages from. | ||
*/ "KeyringOrigin"] = 'keyringOrigin'; | ||
SnapCaveatType[/** | ||
* Caveat specifying the snap IDs that can be interacted with. | ||
@@ -21,0 +24,0 @@ */ "SnapIds"] = 'snapIds'; |
@@ -9,2 +9,3 @@ export var HandlerType; | ||
HandlerType["OnNameLookup"] = 'onNameLookup'; | ||
HandlerType["OnKeyringRequest"] = 'onKeyringRequest'; | ||
})(HandlerType || (HandlerType = {})); | ||
@@ -53,2 +54,9 @@ export const SNAP_EXPORTS = { | ||
} | ||
}, | ||
[HandlerType.OnKeyringRequest]: { | ||
type: HandlerType.OnKeyringRequest, | ||
required: true, | ||
validator: (snapExport)=>{ | ||
return typeof snapExport === 'function'; | ||
} | ||
} | ||
@@ -55,0 +63,0 @@ }; |
@@ -1,11 +0,14 @@ | ||
import { isJsonRpcFailure, isJsonRpcSuccess, assertStruct } from '@metamask/utils'; | ||
import { boolean, object, optional, refine } from 'superstruct'; | ||
import { SubjectType } from '@metamask/permission-controller'; | ||
import { assertStruct, isJsonRpcFailure, isJsonRpcSuccess } from '@metamask/utils'; | ||
import { array, boolean, object, optional, refine, string } from 'superstruct'; | ||
export const RpcOriginsStruct = refine(object({ | ||
dapps: optional(boolean()), | ||
snaps: optional(boolean()) | ||
snaps: optional(boolean()), | ||
allowedOrigins: optional(array(string())) | ||
}), 'RPC origins', (value)=>{ | ||
if (!Object.values(value).some(Boolean)) { | ||
throw new Error('Must specify at least one JSON-RPC origin'); | ||
const hasOrigins = Boolean(value.snaps === true || value.dapps === true || value.allowedOrigins && value.allowedOrigins.length > 0); | ||
if (hasOrigins) { | ||
return true; | ||
} | ||
return true; | ||
return 'Must specify at least one JSON-RPC origin.'; | ||
}); | ||
@@ -23,3 +26,40 @@ /** | ||
} | ||
export const KeyringOriginsStruct = object({ | ||
allowedOrigins: optional(array(string())) | ||
}); | ||
/** | ||
* Assert that the given value is a valid {@link KeyringOrigins} object. | ||
* | ||
* @param value - The value to assert. | ||
* @param ErrorWrapper - An optional error wrapper to use. Defaults to | ||
* {@link AssertionError}. | ||
* @throws If the value is not a valid {@link KeyringOrigins} object. | ||
*/ export function assertIsKeyringOrigins(value, // eslint-disable-next-line @typescript-eslint/naming-convention | ||
ErrorWrapper) { | ||
assertStruct(value, KeyringOriginsStruct, 'Invalid keyring origins', ErrorWrapper); | ||
} | ||
/** | ||
* Check if the given origin is allowed by the given JSON-RPC origins object. | ||
* | ||
* @param origins - The JSON-RPC origins object. | ||
* @param subjectType - The type of the origin. | ||
* @param origin - The origin to check. | ||
* @returns Whether the origin is allowed. | ||
*/ export function isOriginAllowed(origins, subjectType, origin) { | ||
// The MetaMask client is always allowed. | ||
if (origin === 'metamask') { | ||
return true; | ||
} | ||
// If the origin is in the `allowedOrigins` list, it is allowed. | ||
if (origins.allowedOrigins?.includes(origin)) { | ||
return true; | ||
} | ||
// If the origin is a website and `dapps` is true, it is allowed. | ||
if (subjectType === SubjectType.Website && origins.dapps) { | ||
return true; | ||
} | ||
// If the origin is a snap and `snaps` is true, it is allowed. | ||
return Boolean(subjectType === SubjectType.Snap && origins.snaps); | ||
} | ||
/** | ||
* Assert that the given value is a successful JSON-RPC response. If the value | ||
@@ -26,0 +66,0 @@ * is not a success response, an error is thrown. If the value is an JSON-RPC |
@@ -7,3 +7,3 @@ import { isValidBIP32PathSegment } from '@metamask/key-tree'; | ||
import { SIP_6_MAGIC_VALUE, STATE_ENCRYPTION_MAGIC_VALUE } from '../entropy'; | ||
import { RpcOriginsStruct } from '../json-rpc'; | ||
import { KeyringOriginsStruct, RpcOriginsStruct } from '../json-rpc'; | ||
import { ChainIdStruct } from '../namespace'; | ||
@@ -88,2 +88,3 @@ import { SnapIdStruct } from '../snaps'; | ||
'endowment:name-lookup': optional(ChainIdsStruct), | ||
'endowment:keyring': optional(KeyringOriginsStruct), | ||
snap_dialog: optional(object({})), | ||
@@ -90,0 +91,0 @@ // TODO: Remove |
@@ -23,2 +23,6 @@ export declare enum SnapCaveatType { | ||
/** | ||
* The origins that a Snap can receive keyring messages from. | ||
*/ | ||
KeyringOrigin = "keyringOrigin", | ||
/** | ||
* Caveat specifying the snap IDs that can be interacted with. | ||
@@ -25,0 +29,0 @@ */ |
@@ -11,3 +11,4 @@ import type { Component } from '@metamask/snaps-ui'; | ||
OnUpdate = "onUpdate", | ||
OnNameLookup = "onNameLookup" | ||
OnNameLookup = "onNameLookup", | ||
OnKeyringRequest = "onKeyringRequest" | ||
} | ||
@@ -66,2 +67,7 @@ declare type SnapHandler = { | ||
}; | ||
readonly onKeyringRequest: { | ||
readonly type: HandlerType.OnKeyringRequest; | ||
readonly required: true; | ||
readonly validator: (snapExport: unknown) => snapExport is OnKeyringRequestHandler<JsonRpcParams>; | ||
}; | ||
}; | ||
@@ -148,2 +154,15 @@ /** | ||
/** | ||
* The `onKeyringRequest` handler. This is called by the MetaMask client for | ||
* privileged keyring actions. | ||
* | ||
* @param args - The request arguments. | ||
* @param args.origin - The origin of the request. This can be the ID of | ||
* another snap, or the URL of a dapp. | ||
* @param args.request - The JSON-RPC request sent to the snap. | ||
*/ | ||
export declare type OnKeyringRequestHandler<Params extends JsonRpcParams = JsonRpcParams> = (args: { | ||
origin: string; | ||
request: JsonRpcRequest<Params>; | ||
}) => Promise<unknown>; | ||
/** | ||
* Utility type for getting the handler function type from a handler type. | ||
@@ -193,3 +212,3 @@ */ | ||
export declare type SnapFunctionExports = { | ||
[Key in keyof typeof SNAP_EXPORTS]?: HandlerFunction<typeof SNAP_EXPORTS[Key]>; | ||
[Key in keyof typeof SNAP_EXPORTS]?: HandlerFunction<(typeof SNAP_EXPORTS)[Key]>; | ||
}; | ||
@@ -196,0 +215,0 @@ /** |
@@ -1,2 +0,3 @@ | ||
import type { Json, JsonRpcSuccess, AssertionErrorConstructor } from '@metamask/utils'; | ||
import { SubjectType } from '@metamask/permission-controller'; | ||
import type { AssertionErrorConstructor, Json, JsonRpcSuccess } from '@metamask/utils'; | ||
import type { Infer } from 'superstruct'; | ||
@@ -6,5 +7,7 @@ export declare const RpcOriginsStruct: import("superstruct").Struct<{ | ||
snaps?: boolean | undefined; | ||
allowedOrigins?: string[] | undefined; | ||
}, { | ||
dapps: import("superstruct").Struct<boolean | undefined, null>; | ||
snaps: import("superstruct").Struct<boolean | undefined, null>; | ||
allowedOrigins: import("superstruct").Struct<string[] | undefined, import("superstruct").Struct<string, null>>; | ||
}>; | ||
@@ -21,3 +24,27 @@ export declare type RpcOrigins = Infer<typeof RpcOriginsStruct>; | ||
export declare function assertIsRpcOrigins(value: unknown, ErrorWrapper?: AssertionErrorConstructor): asserts value is RpcOrigins; | ||
export declare const KeyringOriginsStruct: import("superstruct").Struct<{ | ||
allowedOrigins?: string[] | undefined; | ||
}, { | ||
allowedOrigins: import("superstruct").Struct<string[] | undefined, import("superstruct").Struct<string, null>>; | ||
}>; | ||
export declare type KeyringOrigins = Infer<typeof KeyringOriginsStruct>; | ||
/** | ||
* Assert that the given value is a valid {@link KeyringOrigins} object. | ||
* | ||
* @param value - The value to assert. | ||
* @param ErrorWrapper - An optional error wrapper to use. Defaults to | ||
* {@link AssertionError}. | ||
* @throws If the value is not a valid {@link KeyringOrigins} object. | ||
*/ | ||
export declare function assertIsKeyringOrigins(value: unknown, ErrorWrapper?: AssertionErrorConstructor): asserts value is KeyringOrigins; | ||
/** | ||
* Check if the given origin is allowed by the given JSON-RPC origins object. | ||
* | ||
* @param origins - The JSON-RPC origins object. | ||
* @param subjectType - The type of the origin. | ||
* @param origin - The origin to check. | ||
* @returns Whether the origin is allowed. | ||
*/ | ||
export declare function isOriginAllowed(origins: RpcOrigins, subjectType: SubjectType, origin: string): boolean; | ||
/** | ||
* Assert that the given value is a successful JSON-RPC response. If the value | ||
@@ -24,0 +51,0 @@ * is not a success response, an error is thrown. If the value is an JSON-RPC |
@@ -58,4 +58,8 @@ import type { Infer, Struct } from 'superstruct'; | ||
snaps?: boolean | undefined; | ||
allowedOrigins?: string[] | undefined; | ||
} | undefined; | ||
'endowment:name-lookup'?: string[] | undefined; | ||
'endowment:keyring'?: { | ||
allowedOrigins?: string[] | undefined; | ||
} | undefined; | ||
snap_dialog?: {} | undefined; | ||
@@ -134,7 +138,14 @@ snap_confirm?: {} | undefined; | ||
snaps?: boolean | undefined; | ||
allowedOrigins?: string[] | undefined; | ||
} | undefined, { | ||
dapps: Struct<boolean | undefined, null>; | ||
snaps: Struct<boolean | undefined, null>; | ||
allowedOrigins: Struct<string[] | undefined, Struct<string, null>>; | ||
}>; | ||
'endowment:name-lookup': Struct<string[] | undefined, Struct<string, null>>; | ||
'endowment:keyring': Struct<{ | ||
allowedOrigins?: string[] | undefined; | ||
} | undefined, { | ||
allowedOrigins: Struct<string[] | undefined, Struct<string, null>>; | ||
}>; | ||
snap_dialog: Struct<{} | undefined, {}>; | ||
@@ -219,4 +230,8 @@ snap_confirm: Struct<{} | undefined, {}>; | ||
snaps?: boolean | undefined; | ||
allowedOrigins?: string[] | undefined; | ||
} | undefined; | ||
'endowment:name-lookup'?: string[] | undefined; | ||
'endowment:keyring'?: { | ||
allowedOrigins?: string[] | undefined; | ||
} | undefined; | ||
snap_dialog?: {} | undefined; | ||
@@ -313,4 +328,8 @@ snap_confirm?: {} | undefined; | ||
snaps?: boolean | undefined; | ||
allowedOrigins?: string[] | undefined; | ||
} | undefined; | ||
'endowment:name-lookup'?: string[] | undefined; | ||
'endowment:keyring'?: { | ||
allowedOrigins?: string[] | undefined; | ||
} | undefined; | ||
snap_dialog?: {} | undefined; | ||
@@ -389,7 +408,14 @@ snap_confirm?: {} | undefined; | ||
snaps?: boolean | undefined; | ||
allowedOrigins?: string[] | undefined; | ||
} | undefined, { | ||
dapps: Struct<boolean | undefined, null>; | ||
snaps: Struct<boolean | undefined, null>; | ||
allowedOrigins: Struct<string[] | undefined, Struct<string, null>>; | ||
}>; | ||
'endowment:name-lookup': Struct<string[] | undefined, Struct<string, null>>; | ||
'endowment:keyring': Struct<{ | ||
allowedOrigins?: string[] | undefined; | ||
} | undefined, { | ||
allowedOrigins: Struct<string[] | undefined, Struct<string, null>>; | ||
}>; | ||
snap_dialog: Struct<{} | undefined, {}>; | ||
@@ -396,0 +422,0 @@ snap_confirm: Struct<{} | undefined, {}>; |
@@ -13,3 +13,3 @@ /// <reference types="node" /> | ||
export declare function readVirtualFile(path: string, encoding?: BufferEncoding | null): Promise<VirtualFile<unknown>>; | ||
declare type WriteVFileOptions = Exclude<Parameters<typeof fsPromises['writeFile']>[2], undefined>; | ||
declare type WriteVFileOptions = Exclude<Parameters<(typeof fsPromises)['writeFile']>[2], undefined>; | ||
/** | ||
@@ -16,0 +16,0 @@ * Writes vfile to filesystem. |
{ | ||
"name": "@metamask/snaps-utils", | ||
"version": "2.0.1", | ||
"version": "3.0.0", | ||
"repository": { | ||
@@ -49,3 +49,3 @@ "type": "git", | ||
"posttest": "ts-node scripts/coverage.ts && rimraf coverage/jest coverage/wdio", | ||
"test:browser": "wdio run wdio.config.ts", | ||
"test:browser": "wdio run wdio.config.js", | ||
"test:ci": "yarn test", | ||
@@ -74,5 +74,5 @@ "lint:eslint": "eslint . --cache --ext js,ts,jsx,tsx", | ||
"@metamask/key-tree": "^9.0.0", | ||
"@metamask/permission-controller": "^4.1.0", | ||
"@metamask/permission-controller": "^4.1.2", | ||
"@metamask/snaps-registry": "^2.0.0", | ||
"@metamask/snaps-ui": "^2.0.0", | ||
"@metamask/snaps-ui": "^3.0.0", | ||
"@metamask/utils": "^8.1.0", | ||
@@ -97,3 +97,3 @@ "@noble/hashes": "^1.3.1", | ||
"@lavamoat/allow-scripts": "^2.5.1", | ||
"@metamask/auto-changelog": "^3.1.0", | ||
"@metamask/auto-changelog": "^3.3.0", | ||
"@metamask/eslint-config": "^12.1.0", | ||
@@ -150,3 +150,3 @@ "@metamask/eslint-config-jest": "^12.1.0", | ||
"engines": { | ||
"node": ">=16.0.0" | ||
"node": "^18.16 || >=20" | ||
}, | ||
@@ -153,0 +153,0 @@ "publishConfig": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
654272
7398
+ Added@metamask/snaps-ui@3.1.0(transitive)
- Removed@metamask/snaps-ui@2.0.0(transitive)
Updated@metamask/snaps-ui@^3.0.0