UNPKG

@metamask/snaps-utils

Version:
197 lines 11.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createSnapManifest = exports.assertIsSnapManifest = exports.isSnapManifest = exports.SnapManifestStruct = exports.InitialConnectionsStruct = exports.SnapAuxilaryFilesStruct = exports.PermissionsStruct = exports.EmptyObjectStruct = exports.HandlerCaveatsStruct = exports.ProtocolScopesStruct = exports.MaxRequestTimeStruct = exports.MAXIMUM_REQUEST_TIMEOUT = exports.MINIMUM_REQUEST_TIMEOUT = exports.LookupMatchersStruct = exports.ChainIdsStruct = exports.SnapIdsStruct = exports.SemVerRangeStruct = exports.SnapGetBip32EntropyPermissionsStruct = exports.Bip32EntropyStruct = exports.CurveStruct = exports.bip32entropy = exports.Bip32PathStruct = exports.FORBIDDEN_COIN_TYPES = void 0; const key_tree_1 = require("@metamask/key-tree"); const superstruct_1 = require("@metamask/superstruct"); const utils_1 = require("@metamask/utils"); const array_1 = require("../array.cjs"); const cronjob_1 = require("../cronjob.cjs"); const entropy_1 = require("../entropy.cjs"); const json_rpc_1 = require("../json-rpc.cjs"); const snaps_1 = require("../snaps.cjs"); const structs_1 = require("../structs.cjs"); const types_1 = require("../types.cjs"); // BIP-43 purposes that cannot be used for entropy derivation. These are in the // string form, ending with `'`. const FORBIDDEN_PURPOSES = [ entropy_1.SIP_6_MAGIC_VALUE, entropy_1.STATE_ENCRYPTION_MAGIC_VALUE, ]; exports.FORBIDDEN_COIN_TYPES = [60]; const FORBIDDEN_PATHS = exports.FORBIDDEN_COIN_TYPES.map((coinType) => [ 'm', "44'", `${coinType}'`, ]); exports.Bip32PathStruct = (0, superstruct_1.refine)((0, superstruct_1.array)((0, superstruct_1.string)()), 'BIP-32 path', (path) => { if (path.length === 0) { return 'Path must be a non-empty BIP-32 derivation path array'; } if (path[0] !== 'm') { return 'Path must start with "m".'; } if (path.length < 3) { return 'Paths must have a length of at least three.'; } if (path.slice(1).some((part) => !(0, key_tree_1.isValidBIP32PathSegment)(part))) { return 'Path must be a valid BIP-32 derivation path array.'; } if (FORBIDDEN_PURPOSES.includes(path[1])) { return `The purpose "${path[1]}" is not allowed for entropy derivation.`; } if (FORBIDDEN_PATHS.some((forbiddenPath) => (0, array_1.isEqual)(path.slice(0, forbiddenPath.length), forbiddenPath))) { return `The path "${path.join('/')}" is not allowed for entropy derivation.`; } return true; }); const bip32entropy = (struct) => (0, superstruct_1.refine)(struct, 'BIP-32 entropy', (value) => { if (value.curve === 'ed25519' && value.path.slice(1).some((part) => !part.endsWith("'"))) { return 'Ed25519 does not support unhardened paths.'; } return true; }); exports.bip32entropy = bip32entropy; exports.CurveStruct = (0, superstruct_1.enums)([ 'ed25519', 'secp256k1', 'ed25519Bip32', ]); // Used outside @metamask/snap-utils exports.Bip32EntropyStruct = (0, exports.bip32entropy)((0, superstruct_1.type)({ path: exports.Bip32PathStruct, curve: exports.CurveStruct, })); exports.SnapGetBip32EntropyPermissionsStruct = (0, superstruct_1.size)((0, superstruct_1.array)(exports.Bip32EntropyStruct), 1, Infinity); exports.SemVerRangeStruct = (0, superstruct_1.refine)((0, superstruct_1.string)(), 'SemVer range', (value) => { if ((0, utils_1.isValidSemVerRange)(value)) { return true; } return 'Expected a valid SemVer range.'; }); exports.SnapIdsStruct = (0, superstruct_1.refine)((0, superstruct_1.record)(snaps_1.SnapIdStruct, (0, superstruct_1.object)({ version: (0, superstruct_1.optional)(exports.SemVerRangeStruct) })), 'SnapIds', (value) => { if (Object.keys(value).length === 0) { return false; } return true; }); exports.ChainIdsStruct = (0, superstruct_1.size)((0, superstruct_1.array)(utils_1.CaipChainIdStruct), 1, Infinity); exports.LookupMatchersStruct = (0, superstruct_1.union)([ (0, superstruct_1.object)({ tlds: (0, superstruct_1.size)((0, superstruct_1.array)((0, superstruct_1.string)()), 1, Infinity), }), (0, superstruct_1.object)({ schemes: (0, superstruct_1.size)((0, superstruct_1.array)((0, superstruct_1.string)()), 1, Infinity), }), (0, superstruct_1.object)({ tlds: (0, superstruct_1.size)((0, superstruct_1.array)((0, superstruct_1.string)()), 1, Infinity), schemes: (0, superstruct_1.size)((0, superstruct_1.array)((0, superstruct_1.string)()), 1, Infinity), }), ]); exports.MINIMUM_REQUEST_TIMEOUT = (0, utils_1.inMilliseconds)(5, utils_1.Duration.Second); exports.MAXIMUM_REQUEST_TIMEOUT = (0, utils_1.inMilliseconds)(3, utils_1.Duration.Minute); exports.MaxRequestTimeStruct = (0, superstruct_1.size)((0, superstruct_1.integer)(), exports.MINIMUM_REQUEST_TIMEOUT, exports.MAXIMUM_REQUEST_TIMEOUT); exports.ProtocolScopesStruct = (0, superstruct_1.record)(utils_1.CaipChainIdStruct, (0, superstruct_1.object)({ methods: (0, superstruct_1.array)((0, superstruct_1.string)()) })); // Utility type to union with for all handler structs exports.HandlerCaveatsStruct = (0, superstruct_1.object)({ maxRequestTime: (0, superstruct_1.optional)(exports.MaxRequestTimeStruct), }); exports.EmptyObjectStruct = (0, superstruct_1.object)({}); /* eslint-disable @typescript-eslint/naming-convention */ exports.PermissionsStruct = (0, superstruct_1.type)({ 'endowment:assets': (0, superstruct_1.optional)((0, structs_1.mergeStructs)(exports.HandlerCaveatsStruct, (0, superstruct_1.object)({ scopes: exports.ChainIdsStruct }))), 'endowment:cronjob': (0, superstruct_1.optional)((0, structs_1.mergeStructs)(exports.HandlerCaveatsStruct, (0, superstruct_1.object)({ jobs: (0, superstruct_1.optional)(cronjob_1.CronjobSpecificationArrayStruct) }))), 'endowment:ethereum-provider': (0, superstruct_1.optional)(exports.EmptyObjectStruct), 'endowment:keyring': (0, superstruct_1.optional)((0, structs_1.mergeStructs)(exports.HandlerCaveatsStruct, json_rpc_1.KeyringOriginsStruct)), 'endowment:protocol': (0, superstruct_1.optional)((0, structs_1.mergeStructs)(exports.HandlerCaveatsStruct, (0, superstruct_1.object)({ scopes: exports.ProtocolScopesStruct }))), 'endowment:lifecycle-hooks': (0, superstruct_1.optional)(exports.HandlerCaveatsStruct), 'endowment:name-lookup': (0, superstruct_1.optional)((0, structs_1.mergeStructs)(exports.HandlerCaveatsStruct, (0, superstruct_1.object)({ chains: (0, superstruct_1.optional)(exports.ChainIdsStruct), matchers: (0, superstruct_1.optional)(exports.LookupMatchersStruct), }))), 'endowment:network-access': (0, superstruct_1.optional)(exports.EmptyObjectStruct), 'endowment:page-home': (0, superstruct_1.optional)(exports.HandlerCaveatsStruct), 'endowment:rpc': (0, superstruct_1.optional)((0, structs_1.mergeStructs)(exports.HandlerCaveatsStruct, json_rpc_1.RpcOriginsStruct)), 'endowment:signature-insight': (0, superstruct_1.optional)((0, structs_1.mergeStructs)(exports.HandlerCaveatsStruct, (0, superstruct_1.object)({ allowSignatureOrigin: (0, superstruct_1.optional)((0, superstruct_1.boolean)()), }))), 'endowment:transaction-insight': (0, superstruct_1.optional)((0, structs_1.mergeStructs)(exports.HandlerCaveatsStruct, (0, superstruct_1.object)({ allowTransactionOrigin: (0, superstruct_1.optional)((0, superstruct_1.boolean)()), }))), 'endowment:webassembly': (0, superstruct_1.optional)(exports.EmptyObjectStruct), snap_dialog: (0, superstruct_1.optional)(exports.EmptyObjectStruct), snap_manageState: (0, superstruct_1.optional)(exports.EmptyObjectStruct), snap_manageAccounts: (0, superstruct_1.optional)(exports.EmptyObjectStruct), snap_notify: (0, superstruct_1.optional)(exports.EmptyObjectStruct), snap_getBip32Entropy: (0, superstruct_1.optional)(exports.SnapGetBip32EntropyPermissionsStruct), snap_getBip32PublicKey: (0, superstruct_1.optional)(exports.SnapGetBip32EntropyPermissionsStruct), snap_getBip44Entropy: (0, superstruct_1.optional)((0, superstruct_1.size)((0, superstruct_1.array)((0, superstruct_1.object)({ coinType: (0, superstruct_1.size)((0, superstruct_1.integer)(), 0, 2 ** 32 - 1) })), 1, Infinity)), snap_getEntropy: (0, superstruct_1.optional)(exports.EmptyObjectStruct), snap_getLocale: (0, superstruct_1.optional)(exports.EmptyObjectStruct), wallet_snap: (0, superstruct_1.optional)(exports.SnapIdsStruct), }); exports.SnapAuxilaryFilesStruct = (0, superstruct_1.array)((0, superstruct_1.string)()); exports.InitialConnectionsStruct = (0, superstruct_1.record)((0, superstruct_1.intersection)([(0, superstruct_1.string)(), (0, types_1.uri)()]), (0, superstruct_1.object)({})); exports.SnapManifestStruct = (0, superstruct_1.object)({ version: utils_1.VersionStruct, description: (0, superstruct_1.size)((0, superstruct_1.string)(), 1, 280), proposedName: (0, superstruct_1.size)((0, superstruct_1.string)(), 1, 214), repository: (0, superstruct_1.optional)((0, superstruct_1.type)({ type: (0, superstruct_1.size)((0, superstruct_1.string)(), 1, Infinity), url: (0, superstruct_1.size)((0, superstruct_1.string)(), 1, Infinity), })), source: (0, superstruct_1.object)({ shasum: utils_1.ChecksumStruct, location: (0, superstruct_1.object)({ npm: (0, superstruct_1.object)({ filePath: (0, superstruct_1.size)((0, superstruct_1.string)(), 1, Infinity), iconPath: (0, superstruct_1.optional)((0, superstruct_1.size)((0, superstruct_1.string)(), 1, Infinity)), packageName: types_1.NameStruct, registry: (0, superstruct_1.union)([ (0, superstruct_1.literal)('https://registry.npmjs.org'), (0, superstruct_1.literal)('https://registry.npmjs.org/'), ]), }), }), files: (0, superstruct_1.optional)(exports.SnapAuxilaryFilesStruct), locales: (0, superstruct_1.optional)(exports.SnapAuxilaryFilesStruct), }), initialConnections: (0, superstruct_1.optional)(exports.InitialConnectionsStruct), initialPermissions: exports.PermissionsStruct, manifestVersion: (0, superstruct_1.literal)('0.1'), platformVersion: (0, superstruct_1.optional)(utils_1.VersionStruct), $schema: (0, superstruct_1.optional)((0, superstruct_1.string)()), // enables JSON-Schema linting in VSC and other IDEs }); /** * Check if the given value is a valid {@link SnapManifest} object. * * @param value - The value to check. * @returns Whether the value is a valid {@link SnapManifest} object. */ function isSnapManifest(value) { return (0, superstruct_1.is)(value, exports.SnapManifestStruct); } exports.isSnapManifest = isSnapManifest; /** * Assert that the given value is a valid {@link SnapManifest} object. * * @param value - The value to check. * @throws If the value is not a valid {@link SnapManifest} object. */ function assertIsSnapManifest(value) { (0, utils_1.assertStruct)(value, exports.SnapManifestStruct, `"${types_1.NpmSnapFileNames.Manifest}" is invalid`); } exports.assertIsSnapManifest = assertIsSnapManifest; /** * Creates a {@link SnapManifest} object from JSON. * * @param value - The value to check. * @throws If the value cannot be coerced to a {@link SnapManifest} object. * @returns The created {@link SnapManifest} object. */ function createSnapManifest(value) { // TODO: Add a utility to prefix these errors similar to assertStruct return (0, superstruct_1.create)(value, exports.SnapManifestStruct); } exports.createSnapManifest = createSnapManifest; //# sourceMappingURL=validation.cjs.map