@metamask/snaps-rpc-methods 11.8.0 → 11.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -1
- package/dist/endowments/cronjob.cjs +8 -0
- package/dist/endowments/cronjob.cjs.map +1 -1
- package/dist/endowments/cronjob.d.cts.map +1 -1
- package/dist/endowments/cronjob.d.mts.map +1 -1
- package/dist/endowments/cronjob.mjs +9 -1
- package/dist/endowments/cronjob.mjs.map +1 -1
- package/dist/permitted/cancelBackgroundEvent.cjs +69 -0
- package/dist/permitted/cancelBackgroundEvent.cjs.map +1 -0
- package/dist/permitted/cancelBackgroundEvent.d.cts +16 -0
- package/dist/permitted/cancelBackgroundEvent.d.cts.map +1 -0
- package/dist/permitted/cancelBackgroundEvent.d.mts +16 -0
- package/dist/permitted/cancelBackgroundEvent.d.mts.map +1 -0
- package/dist/permitted/cancelBackgroundEvent.mjs +66 -0
- package/dist/permitted/cancelBackgroundEvent.mjs.map +1 -0
- package/dist/permitted/clearState.cjs +73 -0
- package/dist/permitted/clearState.cjs.map +1 -0
- package/dist/permitted/clearState.d.cts +28 -0
- package/dist/permitted/clearState.d.cts.map +1 -0
- package/dist/permitted/clearState.d.mts +28 -0
- package/dist/permitted/clearState.d.mts.map +1 -0
- package/dist/permitted/clearState.mjs +70 -0
- package/dist/permitted/clearState.mjs.map +1 -0
- package/dist/permitted/getBackgroundEvents.cjs +42 -0
- package/dist/permitted/getBackgroundEvents.cjs.map +1 -0
- package/dist/permitted/getBackgroundEvents.d.cts +8 -0
- package/dist/permitted/getBackgroundEvents.d.cts.map +1 -0
- package/dist/permitted/getBackgroundEvents.d.mts +8 -0
- package/dist/permitted/getBackgroundEvents.d.mts.map +1 -0
- package/dist/permitted/getBackgroundEvents.mjs +39 -0
- package/dist/permitted/getBackgroundEvents.mjs.map +1 -0
- package/dist/permitted/getState.cjs +118 -0
- package/dist/permitted/getState.cjs.map +1 -0
- package/dist/permitted/getState.d.cts +53 -0
- package/dist/permitted/getState.d.cts.map +1 -0
- package/dist/permitted/getState.d.mts +53 -0
- package/dist/permitted/getState.d.mts.map +1 -0
- package/dist/permitted/getState.mjs +114 -0
- package/dist/permitted/getState.mjs.map +1 -0
- package/dist/permitted/handlers.cjs +12 -0
- package/dist/permitted/handlers.cjs.map +1 -1
- package/dist/permitted/handlers.d.cts +8 -2
- package/dist/permitted/handlers.d.cts.map +1 -1
- package/dist/permitted/handlers.d.mts +8 -2
- package/dist/permitted/handlers.d.mts.map +1 -1
- package/dist/permitted/handlers.mjs +12 -0
- package/dist/permitted/handlers.mjs.map +1 -1
- package/dist/permitted/index.cjs.map +1 -1
- package/dist/permitted/index.d.cts +7 -1
- package/dist/permitted/index.d.cts.map +1 -1
- package/dist/permitted/index.d.mts +7 -1
- package/dist/permitted/index.d.mts.map +1 -1
- package/dist/permitted/index.mjs.map +1 -1
- package/dist/permitted/scheduleBackgroundEvent.cjs +122 -0
- package/dist/permitted/scheduleBackgroundEvent.cjs.map +1 -0
- package/dist/permitted/scheduleBackgroundEvent.d.cts +33 -0
- package/dist/permitted/scheduleBackgroundEvent.d.cts.map +1 -0
- package/dist/permitted/scheduleBackgroundEvent.d.mts +33 -0
- package/dist/permitted/scheduleBackgroundEvent.d.mts.map +1 -0
- package/dist/permitted/scheduleBackgroundEvent.mjs +119 -0
- package/dist/permitted/scheduleBackgroundEvent.mjs.map +1 -0
- package/dist/permitted/setState.cjs +154 -0
- package/dist/permitted/setState.cjs.map +1 -0
- package/dist/permitted/setState.d.cts +65 -0
- package/dist/permitted/setState.d.cts.map +1 -0
- package/dist/permitted/setState.d.mts +65 -0
- package/dist/permitted/setState.d.mts.map +1 -0
- package/dist/permitted/setState.mjs +150 -0
- package/dist/permitted/setState.mjs.map +1 -0
- package/dist/utils.cjs +22 -1
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +9 -0
- package/dist/utils.d.cts.map +1 -1
- package/dist/utils.d.mts +9 -0
- package/dist/utils.d.mts.map +1 -1
- package/dist/utils.mjs +20 -0
- package/dist/utils.mjs.map +1 -1
- package/package.json +11 -9
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.set = exports.setStateHandler = void 0;
|
|
4
|
+
const rpc_errors_1 = require("@metamask/rpc-errors");
|
|
5
|
+
const superstruct_1 = require("@metamask/superstruct");
|
|
6
|
+
const utils_1 = require("@metamask/utils");
|
|
7
|
+
const manageState_1 = require("../restricted/manageState.cjs");
|
|
8
|
+
const utils_2 = require("../utils.cjs");
|
|
9
|
+
const hookNames = {
|
|
10
|
+
hasPermission: true,
|
|
11
|
+
getSnapState: true,
|
|
12
|
+
getUnlockPromise: true,
|
|
13
|
+
updateSnapState: true,
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* `snap_setState` sets the state of the Snap.
|
|
17
|
+
*/
|
|
18
|
+
exports.setStateHandler = {
|
|
19
|
+
methodNames: ['snap_setState'],
|
|
20
|
+
implementation: setStateImplementation,
|
|
21
|
+
hookNames,
|
|
22
|
+
};
|
|
23
|
+
const SetStateParametersStruct = (0, superstruct_1.object)({
|
|
24
|
+
key: (0, superstruct_1.optional)(utils_2.StateKeyStruct),
|
|
25
|
+
value: utils_1.JsonStruct,
|
|
26
|
+
encrypted: (0, superstruct_1.optional)((0, superstruct_1.boolean)()),
|
|
27
|
+
});
|
|
28
|
+
/**
|
|
29
|
+
* The `snap_setState` method implementation.
|
|
30
|
+
*
|
|
31
|
+
* @param request - The JSON-RPC request object.
|
|
32
|
+
* @param response - The JSON-RPC response object.
|
|
33
|
+
* @param _next - The `json-rpc-engine` "next" callback. Not used by this
|
|
34
|
+
* function.
|
|
35
|
+
* @param end - The `json-rpc-engine` "end" callback.
|
|
36
|
+
* @param hooks - The RPC method hooks.
|
|
37
|
+
* @param hooks.hasPermission - Check whether a given origin has a given
|
|
38
|
+
* permission.
|
|
39
|
+
* @param hooks.getSnapState - Get the state of the requesting Snap.
|
|
40
|
+
* @param hooks.getUnlockPromise - Wait for the extension to be unlocked.
|
|
41
|
+
* @param hooks.updateSnapState - Update the state of the requesting Snap.
|
|
42
|
+
* @returns Nothing.
|
|
43
|
+
*/
|
|
44
|
+
async function setStateImplementation(request, response, _next, end, { hasPermission, getSnapState, getUnlockPromise, updateSnapState, }) {
|
|
45
|
+
const { params } = request;
|
|
46
|
+
if (!hasPermission(manageState_1.manageStateBuilder.targetName)) {
|
|
47
|
+
return end(rpc_errors_1.providerErrors.unauthorized());
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const validatedParams = getValidatedParams(params);
|
|
51
|
+
const { key, value, encrypted = true } = validatedParams;
|
|
52
|
+
if (key === undefined && !(0, utils_1.isObject)(value)) {
|
|
53
|
+
return end(rpc_errors_1.rpcErrors.invalidParams('Invalid params: Value must be an object if key is not provided.'));
|
|
54
|
+
}
|
|
55
|
+
if (encrypted) {
|
|
56
|
+
await getUnlockPromise(true);
|
|
57
|
+
}
|
|
58
|
+
const newState = await getNewState(key, value, encrypted, getSnapState);
|
|
59
|
+
await updateSnapState(newState, encrypted);
|
|
60
|
+
response.result = null;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
return end(error);
|
|
64
|
+
}
|
|
65
|
+
return end();
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Validate the parameters of the `snap_setState` method.
|
|
69
|
+
*
|
|
70
|
+
* @param params - The parameters to validate.
|
|
71
|
+
* @returns The validated parameters.
|
|
72
|
+
*/
|
|
73
|
+
function getValidatedParams(params) {
|
|
74
|
+
try {
|
|
75
|
+
return (0, superstruct_1.create)(params, SetStateParametersStruct);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
if (error instanceof superstruct_1.StructError) {
|
|
79
|
+
throw rpc_errors_1.rpcErrors.invalidParams({
|
|
80
|
+
message: `Invalid params: ${error.message}.`,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/* istanbul ignore next */
|
|
84
|
+
throw rpc_errors_1.rpcErrors.internal();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Get the new state of the Snap.
|
|
89
|
+
*
|
|
90
|
+
* If the key is `undefined`, the value is expected to be an object. In this
|
|
91
|
+
* case, the value is returned as the new state.
|
|
92
|
+
*
|
|
93
|
+
* If the key is not `undefined`, the value is set in the state at the key. If
|
|
94
|
+
* the key does not exist, it is created (and any missing intermediate keys are
|
|
95
|
+
* created as well).
|
|
96
|
+
*
|
|
97
|
+
* @param key - The key to set.
|
|
98
|
+
* @param value - The value to set the key to.
|
|
99
|
+
* @param encrypted - Whether the state is encrypted.
|
|
100
|
+
* @param getSnapState - The `getSnapState` hook.
|
|
101
|
+
* @returns The new state of the Snap.
|
|
102
|
+
*/
|
|
103
|
+
async function getNewState(key, value, encrypted, getSnapState) {
|
|
104
|
+
if (key === undefined) {
|
|
105
|
+
(0, utils_1.assert)((0, utils_1.isObject)(value));
|
|
106
|
+
return value;
|
|
107
|
+
}
|
|
108
|
+
const state = await getSnapState(encrypted);
|
|
109
|
+
return set(state, key, value);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Set the value of a key in an object. The key may contain Lodash-style path
|
|
113
|
+
* syntax, e.g., `a.b.c` (with the exception of array syntax). If the key does
|
|
114
|
+
* not exist, it is created (and any missing intermediate keys are created as
|
|
115
|
+
* well).
|
|
116
|
+
*
|
|
117
|
+
* This is a simplified version of Lodash's `set` function, but Lodash doesn't
|
|
118
|
+
* seem to be maintained anymore, so we're using our own implementation.
|
|
119
|
+
*
|
|
120
|
+
* @param object - The object to get the key from.
|
|
121
|
+
* @param key - The key to set.
|
|
122
|
+
* @param value - The value to set the key to.
|
|
123
|
+
* @returns The new object with the key set to the value.
|
|
124
|
+
*/
|
|
125
|
+
function set(
|
|
126
|
+
// eslint-disable-next-line @typescript-eslint/default-param-last
|
|
127
|
+
object, key, value) {
|
|
128
|
+
const keys = key.split('.');
|
|
129
|
+
const requiredObject = object ?? {};
|
|
130
|
+
let currentObject = requiredObject;
|
|
131
|
+
for (let i = 0; i < keys.length; i++) {
|
|
132
|
+
const currentKey = keys[i];
|
|
133
|
+
if (utils_2.FORBIDDEN_KEYS.includes(currentKey)) {
|
|
134
|
+
throw rpc_errors_1.rpcErrors.invalidParams('Invalid params: Key contains forbidden characters.');
|
|
135
|
+
}
|
|
136
|
+
if (i === keys.length - 1) {
|
|
137
|
+
currentObject[currentKey] = value;
|
|
138
|
+
return requiredObject;
|
|
139
|
+
}
|
|
140
|
+
if (!(0, utils_1.hasProperty)(currentObject, currentKey) ||
|
|
141
|
+
currentObject[currentKey] === null) {
|
|
142
|
+
currentObject[currentKey] = {};
|
|
143
|
+
}
|
|
144
|
+
else if (!(0, utils_1.isObject)(currentObject[currentKey])) {
|
|
145
|
+
throw rpc_errors_1.rpcErrors.invalidParams('Invalid params: Cannot overwrite non-object value.');
|
|
146
|
+
}
|
|
147
|
+
currentObject = currentObject[currentKey];
|
|
148
|
+
}
|
|
149
|
+
// This should never be reached.
|
|
150
|
+
/* istanbul ignore next */
|
|
151
|
+
throw new Error('Unexpected error while setting the state.');
|
|
152
|
+
}
|
|
153
|
+
exports.set = set;
|
|
154
|
+
//# sourceMappingURL=setState.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setState.cjs","sourceRoot":"","sources":["../../src/permitted/setState.ts"],"names":[],"mappings":"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","sourcesContent":["import type { JsonRpcEngineEndCallback } from '@metamask/json-rpc-engine';\nimport type { PermittedHandlerExport } from '@metamask/permission-controller';\nimport { providerErrors, rpcErrors } from '@metamask/rpc-errors';\nimport type { SetStateParams, SetStateResult } from '@metamask/snaps-sdk';\nimport type { JsonObject } from '@metamask/snaps-sdk/jsx';\nimport { type InferMatching } from '@metamask/snaps-utils';\nimport {\n boolean,\n create,\n object as objectStruct,\n optional,\n StructError,\n} from '@metamask/superstruct';\nimport type { PendingJsonRpcResponse, JsonRpcRequest } from '@metamask/utils';\nimport {\n hasProperty,\n isObject,\n assert,\n JsonStruct,\n type Json,\n} from '@metamask/utils';\n\nimport { manageStateBuilder } from '../restricted/manageState';\nimport type { MethodHooksObject } from '../utils';\nimport { FORBIDDEN_KEYS, StateKeyStruct } from '../utils';\n\nconst hookNames: MethodHooksObject<SetStateHooks> = {\n hasPermission: true,\n getSnapState: true,\n getUnlockPromise: true,\n updateSnapState: true,\n};\n\n/**\n * `snap_setState` sets the state of the Snap.\n */\nexport const setStateHandler: PermittedHandlerExport<\n SetStateHooks,\n SetStateParameters,\n SetStateResult\n> = {\n methodNames: ['snap_setState'],\n implementation: setStateImplementation,\n hookNames,\n};\n\nexport type SetStateHooks = {\n /**\n * Check if the requesting origin has a given permission.\n *\n * @param permissionName - The name of the permission to check.\n * @returns Whether the origin has the permission.\n */\n hasPermission: (permissionName: string) => boolean;\n\n /**\n * Get the state of the requesting Snap.\n *\n * @param encrypted - Whether the state is encrypted.\n * @returns The current state of the Snap.\n */\n getSnapState: (encrypted: boolean) => Promise<Record<string, Json>>;\n\n /**\n * Wait for the extension to be unlocked.\n *\n * @returns A promise that resolves once the extension is unlocked.\n */\n getUnlockPromise: (shouldShowUnlockRequest: boolean) => Promise<void>;\n\n /**\n * Update the state of the requesting Snap.\n *\n * @param newState - The new state of the Snap.\n * @param encrypted - Whether the state should be encrypted.\n */\n updateSnapState: (\n newState: Record<string, Json>,\n encrypted: boolean,\n ) => Promise<void>;\n};\n\nconst SetStateParametersStruct = objectStruct({\n key: optional(StateKeyStruct),\n value: JsonStruct,\n encrypted: optional(boolean()),\n});\n\nexport type SetStateParameters = InferMatching<\n typeof SetStateParametersStruct,\n SetStateParams\n>;\n\n/**\n * The `snap_setState` method implementation.\n *\n * @param request - The JSON-RPC request object.\n * @param response - The JSON-RPC response object.\n * @param _next - The `json-rpc-engine` \"next\" callback. Not used by this\n * function.\n * @param end - The `json-rpc-engine` \"end\" callback.\n * @param hooks - The RPC method hooks.\n * @param hooks.hasPermission - Check whether a given origin has a given\n * permission.\n * @param hooks.getSnapState - Get the state of the requesting Snap.\n * @param hooks.getUnlockPromise - Wait for the extension to be unlocked.\n * @param hooks.updateSnapState - Update the state of the requesting Snap.\n * @returns Nothing.\n */\nasync function setStateImplementation(\n request: JsonRpcRequest<SetStateParameters>,\n response: PendingJsonRpcResponse<SetStateResult>,\n _next: unknown,\n end: JsonRpcEngineEndCallback,\n {\n hasPermission,\n getSnapState,\n getUnlockPromise,\n updateSnapState,\n }: SetStateHooks,\n): Promise<void> {\n const { params } = request;\n\n if (!hasPermission(manageStateBuilder.targetName)) {\n return end(providerErrors.unauthorized());\n }\n\n try {\n const validatedParams = getValidatedParams(params);\n const { key, value, encrypted = true } = validatedParams;\n\n if (key === undefined && !isObject(value)) {\n return end(\n rpcErrors.invalidParams(\n 'Invalid params: Value must be an object if key is not provided.',\n ),\n );\n }\n\n if (encrypted) {\n await getUnlockPromise(true);\n }\n\n const newState = await getNewState(key, value, encrypted, getSnapState);\n await updateSnapState(newState, encrypted);\n response.result = null;\n } catch (error) {\n return end(error);\n }\n\n return end();\n}\n\n/**\n * Validate the parameters of the `snap_setState` method.\n *\n * @param params - The parameters to validate.\n * @returns The validated parameters.\n */\nfunction getValidatedParams(params?: unknown) {\n try {\n return create(params, SetStateParametersStruct);\n } catch (error) {\n if (error instanceof StructError) {\n throw rpcErrors.invalidParams({\n message: `Invalid params: ${error.message}.`,\n });\n }\n\n /* istanbul ignore next */\n throw rpcErrors.internal();\n }\n}\n\n/**\n * Get the new state of the Snap.\n *\n * If the key is `undefined`, the value is expected to be an object. In this\n * case, the value is returned as the new state.\n *\n * If the key is not `undefined`, the value is set in the state at the key. If\n * the key does not exist, it is created (and any missing intermediate keys are\n * created as well).\n *\n * @param key - The key to set.\n * @param value - The value to set the key to.\n * @param encrypted - Whether the state is encrypted.\n * @param getSnapState - The `getSnapState` hook.\n * @returns The new state of the Snap.\n */\nasync function getNewState(\n key: string | undefined,\n value: Json,\n encrypted: boolean,\n getSnapState: SetStateHooks['getSnapState'],\n) {\n if (key === undefined) {\n assert(isObject(value));\n return value;\n }\n\n const state = await getSnapState(encrypted);\n return set(state, key, value);\n}\n\n/**\n * Set the value of a key in an object. The key may contain Lodash-style path\n * syntax, e.g., `a.b.c` (with the exception of array syntax). If the key does\n * not exist, it is created (and any missing intermediate keys are created as\n * well).\n *\n * This is a simplified version of Lodash's `set` function, but Lodash doesn't\n * seem to be maintained anymore, so we're using our own implementation.\n *\n * @param object - The object to get the key from.\n * @param key - The key to set.\n * @param value - The value to set the key to.\n * @returns The new object with the key set to the value.\n */\nexport function set(\n // eslint-disable-next-line @typescript-eslint/default-param-last\n object: Record<string, Json> | null,\n key: string,\n value: Json,\n): JsonObject {\n const keys = key.split('.');\n const requiredObject = object ?? {};\n let currentObject: Record<string, Json> = requiredObject;\n\n for (let i = 0; i < keys.length; i++) {\n const currentKey = keys[i];\n if (FORBIDDEN_KEYS.includes(currentKey)) {\n throw rpcErrors.invalidParams(\n 'Invalid params: Key contains forbidden characters.',\n );\n }\n\n if (i === keys.length - 1) {\n currentObject[currentKey] = value;\n return requiredObject;\n }\n\n if (\n !hasProperty(currentObject, currentKey) ||\n currentObject[currentKey] === null\n ) {\n currentObject[currentKey] = {};\n } else if (!isObject(currentObject[currentKey])) {\n throw rpcErrors.invalidParams(\n 'Invalid params: Cannot overwrite non-object value.',\n );\n }\n\n currentObject = currentObject[currentKey] as Record<string, Json>;\n }\n\n // This should never be reached.\n /* istanbul ignore next */\n throw new Error('Unexpected error while setting the state.');\n}\n"]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { PermittedHandlerExport } from "@metamask/permission-controller";
|
|
2
|
+
import type { SetStateParams, SetStateResult } from "@metamask/snaps-sdk";
|
|
3
|
+
import type { JsonObject } from "@metamask/snaps-sdk/jsx";
|
|
4
|
+
import { type InferMatching } from "@metamask/snaps-utils";
|
|
5
|
+
import { type Json } from "@metamask/utils";
|
|
6
|
+
/**
|
|
7
|
+
* `snap_setState` sets the state of the Snap.
|
|
8
|
+
*/
|
|
9
|
+
export declare const setStateHandler: PermittedHandlerExport<SetStateHooks, SetStateParameters, SetStateResult>;
|
|
10
|
+
export type SetStateHooks = {
|
|
11
|
+
/**
|
|
12
|
+
* Check if the requesting origin has a given permission.
|
|
13
|
+
*
|
|
14
|
+
* @param permissionName - The name of the permission to check.
|
|
15
|
+
* @returns Whether the origin has the permission.
|
|
16
|
+
*/
|
|
17
|
+
hasPermission: (permissionName: string) => boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Get the state of the requesting Snap.
|
|
20
|
+
*
|
|
21
|
+
* @param encrypted - Whether the state is encrypted.
|
|
22
|
+
* @returns The current state of the Snap.
|
|
23
|
+
*/
|
|
24
|
+
getSnapState: (encrypted: boolean) => Promise<Record<string, Json>>;
|
|
25
|
+
/**
|
|
26
|
+
* Wait for the extension to be unlocked.
|
|
27
|
+
*
|
|
28
|
+
* @returns A promise that resolves once the extension is unlocked.
|
|
29
|
+
*/
|
|
30
|
+
getUnlockPromise: (shouldShowUnlockRequest: boolean) => Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Update the state of the requesting Snap.
|
|
33
|
+
*
|
|
34
|
+
* @param newState - The new state of the Snap.
|
|
35
|
+
* @param encrypted - Whether the state should be encrypted.
|
|
36
|
+
*/
|
|
37
|
+
updateSnapState: (newState: Record<string, Json>, encrypted: boolean) => Promise<void>;
|
|
38
|
+
};
|
|
39
|
+
declare const SetStateParametersStruct: import("@metamask/superstruct").Struct<{
|
|
40
|
+
value: Json;
|
|
41
|
+
key?: string | undefined;
|
|
42
|
+
encrypted?: boolean | undefined;
|
|
43
|
+
}, {
|
|
44
|
+
key: import("@metamask/superstruct").Struct<string | undefined, null>;
|
|
45
|
+
value: import("@metamask/superstruct").Struct<Json, unknown>;
|
|
46
|
+
encrypted: import("@metamask/superstruct").Struct<boolean | undefined, null>;
|
|
47
|
+
}>;
|
|
48
|
+
export type SetStateParameters = InferMatching<typeof SetStateParametersStruct, SetStateParams>;
|
|
49
|
+
/**
|
|
50
|
+
* Set the value of a key in an object. The key may contain Lodash-style path
|
|
51
|
+
* syntax, e.g., `a.b.c` (with the exception of array syntax). If the key does
|
|
52
|
+
* not exist, it is created (and any missing intermediate keys are created as
|
|
53
|
+
* well).
|
|
54
|
+
*
|
|
55
|
+
* This is a simplified version of Lodash's `set` function, but Lodash doesn't
|
|
56
|
+
* seem to be maintained anymore, so we're using our own implementation.
|
|
57
|
+
*
|
|
58
|
+
* @param object - The object to get the key from.
|
|
59
|
+
* @param key - The key to set.
|
|
60
|
+
* @param value - The value to set the key to.
|
|
61
|
+
* @returns The new object with the key set to the value.
|
|
62
|
+
*/
|
|
63
|
+
export declare function set(object: Record<string, Json> | null, key: string, value: Json): JsonObject;
|
|
64
|
+
export {};
|
|
65
|
+
//# sourceMappingURL=setState.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setState.d.cts","sourceRoot":"","sources":["../../src/permitted/setState.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,wCAAwC;AAE9E,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,4BAA4B;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,gCAAgC;AAC1D,OAAO,EAAE,KAAK,aAAa,EAAE,8BAA8B;AAS3D,OAAO,EAKL,KAAK,IAAI,EACV,wBAAwB;AAazB;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,sBAAsB,CAClD,aAAa,EACb,kBAAkB,EAClB,cAAc,CAKf,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;;OAKG;IACH,aAAa,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC;IAEnD;;;;;OAKG;IACH,YAAY,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IAEpE;;;;OAIG;IACH,gBAAgB,EAAE,CAAC,uBAAuB,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtE;;;;;OAKG;IACH,eAAe,EAAE,CACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,EAC9B,SAAS,EAAE,OAAO,KACf,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAEF,QAAA,MAAM,wBAAwB;;;;;;;;EAI5B,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,aAAa,CAC5C,OAAO,wBAAwB,EAC/B,cAAc,CACf,CAAC;AAkHF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,GAAG,CAEjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,IAAI,EACnC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,IAAI,GACV,UAAU,CAmCZ"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { PermittedHandlerExport } from "@metamask/permission-controller";
|
|
2
|
+
import type { SetStateParams, SetStateResult } from "@metamask/snaps-sdk";
|
|
3
|
+
import type { JsonObject } from "@metamask/snaps-sdk/jsx";
|
|
4
|
+
import { type InferMatching } from "@metamask/snaps-utils";
|
|
5
|
+
import { type Json } from "@metamask/utils";
|
|
6
|
+
/**
|
|
7
|
+
* `snap_setState` sets the state of the Snap.
|
|
8
|
+
*/
|
|
9
|
+
export declare const setStateHandler: PermittedHandlerExport<SetStateHooks, SetStateParameters, SetStateResult>;
|
|
10
|
+
export type SetStateHooks = {
|
|
11
|
+
/**
|
|
12
|
+
* Check if the requesting origin has a given permission.
|
|
13
|
+
*
|
|
14
|
+
* @param permissionName - The name of the permission to check.
|
|
15
|
+
* @returns Whether the origin has the permission.
|
|
16
|
+
*/
|
|
17
|
+
hasPermission: (permissionName: string) => boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Get the state of the requesting Snap.
|
|
20
|
+
*
|
|
21
|
+
* @param encrypted - Whether the state is encrypted.
|
|
22
|
+
* @returns The current state of the Snap.
|
|
23
|
+
*/
|
|
24
|
+
getSnapState: (encrypted: boolean) => Promise<Record<string, Json>>;
|
|
25
|
+
/**
|
|
26
|
+
* Wait for the extension to be unlocked.
|
|
27
|
+
*
|
|
28
|
+
* @returns A promise that resolves once the extension is unlocked.
|
|
29
|
+
*/
|
|
30
|
+
getUnlockPromise: (shouldShowUnlockRequest: boolean) => Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Update the state of the requesting Snap.
|
|
33
|
+
*
|
|
34
|
+
* @param newState - The new state of the Snap.
|
|
35
|
+
* @param encrypted - Whether the state should be encrypted.
|
|
36
|
+
*/
|
|
37
|
+
updateSnapState: (newState: Record<string, Json>, encrypted: boolean) => Promise<void>;
|
|
38
|
+
};
|
|
39
|
+
declare const SetStateParametersStruct: import("@metamask/superstruct").Struct<{
|
|
40
|
+
value: Json;
|
|
41
|
+
key?: string | undefined;
|
|
42
|
+
encrypted?: boolean | undefined;
|
|
43
|
+
}, {
|
|
44
|
+
key: import("@metamask/superstruct").Struct<string | undefined, null>;
|
|
45
|
+
value: import("@metamask/superstruct").Struct<Json, unknown>;
|
|
46
|
+
encrypted: import("@metamask/superstruct").Struct<boolean | undefined, null>;
|
|
47
|
+
}>;
|
|
48
|
+
export type SetStateParameters = InferMatching<typeof SetStateParametersStruct, SetStateParams>;
|
|
49
|
+
/**
|
|
50
|
+
* Set the value of a key in an object. The key may contain Lodash-style path
|
|
51
|
+
* syntax, e.g., `a.b.c` (with the exception of array syntax). If the key does
|
|
52
|
+
* not exist, it is created (and any missing intermediate keys are created as
|
|
53
|
+
* well).
|
|
54
|
+
*
|
|
55
|
+
* This is a simplified version of Lodash's `set` function, but Lodash doesn't
|
|
56
|
+
* seem to be maintained anymore, so we're using our own implementation.
|
|
57
|
+
*
|
|
58
|
+
* @param object - The object to get the key from.
|
|
59
|
+
* @param key - The key to set.
|
|
60
|
+
* @param value - The value to set the key to.
|
|
61
|
+
* @returns The new object with the key set to the value.
|
|
62
|
+
*/
|
|
63
|
+
export declare function set(object: Record<string, Json> | null, key: string, value: Json): JsonObject;
|
|
64
|
+
export {};
|
|
65
|
+
//# sourceMappingURL=setState.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setState.d.mts","sourceRoot":"","sources":["../../src/permitted/setState.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,wCAAwC;AAE9E,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,4BAA4B;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,gCAAgC;AAC1D,OAAO,EAAE,KAAK,aAAa,EAAE,8BAA8B;AAS3D,OAAO,EAKL,KAAK,IAAI,EACV,wBAAwB;AAazB;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,sBAAsB,CAClD,aAAa,EACb,kBAAkB,EAClB,cAAc,CAKf,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;;OAKG;IACH,aAAa,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC;IAEnD;;;;;OAKG;IACH,YAAY,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IAEpE;;;;OAIG;IACH,gBAAgB,EAAE,CAAC,uBAAuB,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtE;;;;;OAKG;IACH,eAAe,EAAE,CACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,EAC9B,SAAS,EAAE,OAAO,KACf,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAEF,QAAA,MAAM,wBAAwB;;;;;;;;EAI5B,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,aAAa,CAC5C,OAAO,wBAAwB,EAC/B,cAAc,CACf,CAAC;AAkHF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,GAAG,CAEjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,IAAI,EACnC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,IAAI,GACV,UAAU,CAmCZ"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { providerErrors, rpcErrors } from "@metamask/rpc-errors";
|
|
2
|
+
import { boolean, create, object as objectStruct, optional, StructError } from "@metamask/superstruct";
|
|
3
|
+
import { hasProperty, isObject, assert, JsonStruct } from "@metamask/utils";
|
|
4
|
+
import { manageStateBuilder } from "../restricted/manageState.mjs";
|
|
5
|
+
import { FORBIDDEN_KEYS, StateKeyStruct } from "../utils.mjs";
|
|
6
|
+
const hookNames = {
|
|
7
|
+
hasPermission: true,
|
|
8
|
+
getSnapState: true,
|
|
9
|
+
getUnlockPromise: true,
|
|
10
|
+
updateSnapState: true,
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* `snap_setState` sets the state of the Snap.
|
|
14
|
+
*/
|
|
15
|
+
export const setStateHandler = {
|
|
16
|
+
methodNames: ['snap_setState'],
|
|
17
|
+
implementation: setStateImplementation,
|
|
18
|
+
hookNames,
|
|
19
|
+
};
|
|
20
|
+
const SetStateParametersStruct = objectStruct({
|
|
21
|
+
key: optional(StateKeyStruct),
|
|
22
|
+
value: JsonStruct,
|
|
23
|
+
encrypted: optional(boolean()),
|
|
24
|
+
});
|
|
25
|
+
/**
|
|
26
|
+
* The `snap_setState` method implementation.
|
|
27
|
+
*
|
|
28
|
+
* @param request - The JSON-RPC request object.
|
|
29
|
+
* @param response - The JSON-RPC response object.
|
|
30
|
+
* @param _next - The `json-rpc-engine` "next" callback. Not used by this
|
|
31
|
+
* function.
|
|
32
|
+
* @param end - The `json-rpc-engine` "end" callback.
|
|
33
|
+
* @param hooks - The RPC method hooks.
|
|
34
|
+
* @param hooks.hasPermission - Check whether a given origin has a given
|
|
35
|
+
* permission.
|
|
36
|
+
* @param hooks.getSnapState - Get the state of the requesting Snap.
|
|
37
|
+
* @param hooks.getUnlockPromise - Wait for the extension to be unlocked.
|
|
38
|
+
* @param hooks.updateSnapState - Update the state of the requesting Snap.
|
|
39
|
+
* @returns Nothing.
|
|
40
|
+
*/
|
|
41
|
+
async function setStateImplementation(request, response, _next, end, { hasPermission, getSnapState, getUnlockPromise, updateSnapState, }) {
|
|
42
|
+
const { params } = request;
|
|
43
|
+
if (!hasPermission(manageStateBuilder.targetName)) {
|
|
44
|
+
return end(providerErrors.unauthorized());
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const validatedParams = getValidatedParams(params);
|
|
48
|
+
const { key, value, encrypted = true } = validatedParams;
|
|
49
|
+
if (key === undefined && !isObject(value)) {
|
|
50
|
+
return end(rpcErrors.invalidParams('Invalid params: Value must be an object if key is not provided.'));
|
|
51
|
+
}
|
|
52
|
+
if (encrypted) {
|
|
53
|
+
await getUnlockPromise(true);
|
|
54
|
+
}
|
|
55
|
+
const newState = await getNewState(key, value, encrypted, getSnapState);
|
|
56
|
+
await updateSnapState(newState, encrypted);
|
|
57
|
+
response.result = null;
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
return end(error);
|
|
61
|
+
}
|
|
62
|
+
return end();
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Validate the parameters of the `snap_setState` method.
|
|
66
|
+
*
|
|
67
|
+
* @param params - The parameters to validate.
|
|
68
|
+
* @returns The validated parameters.
|
|
69
|
+
*/
|
|
70
|
+
function getValidatedParams(params) {
|
|
71
|
+
try {
|
|
72
|
+
return create(params, SetStateParametersStruct);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
if (error instanceof StructError) {
|
|
76
|
+
throw rpcErrors.invalidParams({
|
|
77
|
+
message: `Invalid params: ${error.message}.`,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/* istanbul ignore next */
|
|
81
|
+
throw rpcErrors.internal();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get the new state of the Snap.
|
|
86
|
+
*
|
|
87
|
+
* If the key is `undefined`, the value is expected to be an object. In this
|
|
88
|
+
* case, the value is returned as the new state.
|
|
89
|
+
*
|
|
90
|
+
* If the key is not `undefined`, the value is set in the state at the key. If
|
|
91
|
+
* the key does not exist, it is created (and any missing intermediate keys are
|
|
92
|
+
* created as well).
|
|
93
|
+
*
|
|
94
|
+
* @param key - The key to set.
|
|
95
|
+
* @param value - The value to set the key to.
|
|
96
|
+
* @param encrypted - Whether the state is encrypted.
|
|
97
|
+
* @param getSnapState - The `getSnapState` hook.
|
|
98
|
+
* @returns The new state of the Snap.
|
|
99
|
+
*/
|
|
100
|
+
async function getNewState(key, value, encrypted, getSnapState) {
|
|
101
|
+
if (key === undefined) {
|
|
102
|
+
assert(isObject(value));
|
|
103
|
+
return value;
|
|
104
|
+
}
|
|
105
|
+
const state = await getSnapState(encrypted);
|
|
106
|
+
return set(state, key, value);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Set the value of a key in an object. The key may contain Lodash-style path
|
|
110
|
+
* syntax, e.g., `a.b.c` (with the exception of array syntax). If the key does
|
|
111
|
+
* not exist, it is created (and any missing intermediate keys are created as
|
|
112
|
+
* well).
|
|
113
|
+
*
|
|
114
|
+
* This is a simplified version of Lodash's `set` function, but Lodash doesn't
|
|
115
|
+
* seem to be maintained anymore, so we're using our own implementation.
|
|
116
|
+
*
|
|
117
|
+
* @param object - The object to get the key from.
|
|
118
|
+
* @param key - The key to set.
|
|
119
|
+
* @param value - The value to set the key to.
|
|
120
|
+
* @returns The new object with the key set to the value.
|
|
121
|
+
*/
|
|
122
|
+
export function set(
|
|
123
|
+
// eslint-disable-next-line @typescript-eslint/default-param-last
|
|
124
|
+
object, key, value) {
|
|
125
|
+
const keys = key.split('.');
|
|
126
|
+
const requiredObject = object ?? {};
|
|
127
|
+
let currentObject = requiredObject;
|
|
128
|
+
for (let i = 0; i < keys.length; i++) {
|
|
129
|
+
const currentKey = keys[i];
|
|
130
|
+
if (FORBIDDEN_KEYS.includes(currentKey)) {
|
|
131
|
+
throw rpcErrors.invalidParams('Invalid params: Key contains forbidden characters.');
|
|
132
|
+
}
|
|
133
|
+
if (i === keys.length - 1) {
|
|
134
|
+
currentObject[currentKey] = value;
|
|
135
|
+
return requiredObject;
|
|
136
|
+
}
|
|
137
|
+
if (!hasProperty(currentObject, currentKey) ||
|
|
138
|
+
currentObject[currentKey] === null) {
|
|
139
|
+
currentObject[currentKey] = {};
|
|
140
|
+
}
|
|
141
|
+
else if (!isObject(currentObject[currentKey])) {
|
|
142
|
+
throw rpcErrors.invalidParams('Invalid params: Cannot overwrite non-object value.');
|
|
143
|
+
}
|
|
144
|
+
currentObject = currentObject[currentKey];
|
|
145
|
+
}
|
|
146
|
+
// This should never be reached.
|
|
147
|
+
/* istanbul ignore next */
|
|
148
|
+
throw new Error('Unexpected error while setting the state.');
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=setState.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setState.mjs","sourceRoot":"","sources":["../../src/permitted/setState.ts"],"names":[],"mappings":"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","sourcesContent":["import type { JsonRpcEngineEndCallback } from '@metamask/json-rpc-engine';\nimport type { PermittedHandlerExport } from '@metamask/permission-controller';\nimport { providerErrors, rpcErrors } from '@metamask/rpc-errors';\nimport type { SetStateParams, SetStateResult } from '@metamask/snaps-sdk';\nimport type { JsonObject } from '@metamask/snaps-sdk/jsx';\nimport { type InferMatching } from '@metamask/snaps-utils';\nimport {\n boolean,\n create,\n object as objectStruct,\n optional,\n StructError,\n} from '@metamask/superstruct';\nimport type { PendingJsonRpcResponse, JsonRpcRequest } from '@metamask/utils';\nimport {\n hasProperty,\n isObject,\n assert,\n JsonStruct,\n type Json,\n} from '@metamask/utils';\n\nimport { manageStateBuilder } from '../restricted/manageState';\nimport type { MethodHooksObject } from '../utils';\nimport { FORBIDDEN_KEYS, StateKeyStruct } from '../utils';\n\nconst hookNames: MethodHooksObject<SetStateHooks> = {\n hasPermission: true,\n getSnapState: true,\n getUnlockPromise: true,\n updateSnapState: true,\n};\n\n/**\n * `snap_setState` sets the state of the Snap.\n */\nexport const setStateHandler: PermittedHandlerExport<\n SetStateHooks,\n SetStateParameters,\n SetStateResult\n> = {\n methodNames: ['snap_setState'],\n implementation: setStateImplementation,\n hookNames,\n};\n\nexport type SetStateHooks = {\n /**\n * Check if the requesting origin has a given permission.\n *\n * @param permissionName - The name of the permission to check.\n * @returns Whether the origin has the permission.\n */\n hasPermission: (permissionName: string) => boolean;\n\n /**\n * Get the state of the requesting Snap.\n *\n * @param encrypted - Whether the state is encrypted.\n * @returns The current state of the Snap.\n */\n getSnapState: (encrypted: boolean) => Promise<Record<string, Json>>;\n\n /**\n * Wait for the extension to be unlocked.\n *\n * @returns A promise that resolves once the extension is unlocked.\n */\n getUnlockPromise: (shouldShowUnlockRequest: boolean) => Promise<void>;\n\n /**\n * Update the state of the requesting Snap.\n *\n * @param newState - The new state of the Snap.\n * @param encrypted - Whether the state should be encrypted.\n */\n updateSnapState: (\n newState: Record<string, Json>,\n encrypted: boolean,\n ) => Promise<void>;\n};\n\nconst SetStateParametersStruct = objectStruct({\n key: optional(StateKeyStruct),\n value: JsonStruct,\n encrypted: optional(boolean()),\n});\n\nexport type SetStateParameters = InferMatching<\n typeof SetStateParametersStruct,\n SetStateParams\n>;\n\n/**\n * The `snap_setState` method implementation.\n *\n * @param request - The JSON-RPC request object.\n * @param response - The JSON-RPC response object.\n * @param _next - The `json-rpc-engine` \"next\" callback. Not used by this\n * function.\n * @param end - The `json-rpc-engine` \"end\" callback.\n * @param hooks - The RPC method hooks.\n * @param hooks.hasPermission - Check whether a given origin has a given\n * permission.\n * @param hooks.getSnapState - Get the state of the requesting Snap.\n * @param hooks.getUnlockPromise - Wait for the extension to be unlocked.\n * @param hooks.updateSnapState - Update the state of the requesting Snap.\n * @returns Nothing.\n */\nasync function setStateImplementation(\n request: JsonRpcRequest<SetStateParameters>,\n response: PendingJsonRpcResponse<SetStateResult>,\n _next: unknown,\n end: JsonRpcEngineEndCallback,\n {\n hasPermission,\n getSnapState,\n getUnlockPromise,\n updateSnapState,\n }: SetStateHooks,\n): Promise<void> {\n const { params } = request;\n\n if (!hasPermission(manageStateBuilder.targetName)) {\n return end(providerErrors.unauthorized());\n }\n\n try {\n const validatedParams = getValidatedParams(params);\n const { key, value, encrypted = true } = validatedParams;\n\n if (key === undefined && !isObject(value)) {\n return end(\n rpcErrors.invalidParams(\n 'Invalid params: Value must be an object if key is not provided.',\n ),\n );\n }\n\n if (encrypted) {\n await getUnlockPromise(true);\n }\n\n const newState = await getNewState(key, value, encrypted, getSnapState);\n await updateSnapState(newState, encrypted);\n response.result = null;\n } catch (error) {\n return end(error);\n }\n\n return end();\n}\n\n/**\n * Validate the parameters of the `snap_setState` method.\n *\n * @param params - The parameters to validate.\n * @returns The validated parameters.\n */\nfunction getValidatedParams(params?: unknown) {\n try {\n return create(params, SetStateParametersStruct);\n } catch (error) {\n if (error instanceof StructError) {\n throw rpcErrors.invalidParams({\n message: `Invalid params: ${error.message}.`,\n });\n }\n\n /* istanbul ignore next */\n throw rpcErrors.internal();\n }\n}\n\n/**\n * Get the new state of the Snap.\n *\n * If the key is `undefined`, the value is expected to be an object. In this\n * case, the value is returned as the new state.\n *\n * If the key is not `undefined`, the value is set in the state at the key. If\n * the key does not exist, it is created (and any missing intermediate keys are\n * created as well).\n *\n * @param key - The key to set.\n * @param value - The value to set the key to.\n * @param encrypted - Whether the state is encrypted.\n * @param getSnapState - The `getSnapState` hook.\n * @returns The new state of the Snap.\n */\nasync function getNewState(\n key: string | undefined,\n value: Json,\n encrypted: boolean,\n getSnapState: SetStateHooks['getSnapState'],\n) {\n if (key === undefined) {\n assert(isObject(value));\n return value;\n }\n\n const state = await getSnapState(encrypted);\n return set(state, key, value);\n}\n\n/**\n * Set the value of a key in an object. The key may contain Lodash-style path\n * syntax, e.g., `a.b.c` (with the exception of array syntax). If the key does\n * not exist, it is created (and any missing intermediate keys are created as\n * well).\n *\n * This is a simplified version of Lodash's `set` function, but Lodash doesn't\n * seem to be maintained anymore, so we're using our own implementation.\n *\n * @param object - The object to get the key from.\n * @param key - The key to set.\n * @param value - The value to set the key to.\n * @returns The new object with the key set to the value.\n */\nexport function set(\n // eslint-disable-next-line @typescript-eslint/default-param-last\n object: Record<string, Json> | null,\n key: string,\n value: Json,\n): JsonObject {\n const keys = key.split('.');\n const requiredObject = object ?? {};\n let currentObject: Record<string, Json> = requiredObject;\n\n for (let i = 0; i < keys.length; i++) {\n const currentKey = keys[i];\n if (FORBIDDEN_KEYS.includes(currentKey)) {\n throw rpcErrors.invalidParams(\n 'Invalid params: Key contains forbidden characters.',\n );\n }\n\n if (i === keys.length - 1) {\n currentObject[currentKey] = value;\n return requiredObject;\n }\n\n if (\n !hasProperty(currentObject, currentKey) ||\n currentObject[currentKey] === null\n ) {\n currentObject[currentKey] = {};\n } else if (!isObject(currentObject[currentKey])) {\n throw rpcErrors.invalidParams(\n 'Invalid params: Cannot overwrite non-object value.',\n );\n }\n\n currentObject = currentObject[currentKey] as Record<string, Json>;\n }\n\n // This should never be reached.\n /* istanbul ignore next */\n throw new Error('Unexpected error while setting the state.');\n}\n"]}
|
package/dist/utils.cjs
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getNode = exports.getPathPrefix = exports.deriveEntropy = exports.selectHooks = void 0;
|
|
3
|
+
exports.StateKeyStruct = exports.isValidStateKey = exports.getNode = exports.getPathPrefix = exports.deriveEntropy = exports.selectHooks = exports.FORBIDDEN_KEYS = void 0;
|
|
4
4
|
const key_tree_1 = require("@metamask/key-tree");
|
|
5
|
+
const superstruct_1 = require("@metamask/superstruct");
|
|
5
6
|
const utils_1 = require("@metamask/utils");
|
|
6
7
|
const sha3_1 = require("@noble/hashes/sha3");
|
|
7
8
|
const HARDENED_VALUE = 0x80000000;
|
|
9
|
+
exports.FORBIDDEN_KEYS = ['constructor', '__proto__', 'prototype'];
|
|
8
10
|
/**
|
|
9
11
|
* Returns the subset of the specified `hooks` that are included in the
|
|
10
12
|
* `hookNames` object. This is a Principle of Least Authority (POLA) measure
|
|
@@ -141,4 +143,23 @@ async function getNode({ curve, secretRecoveryPhrase, path, cryptographicFunctio
|
|
|
141
143
|
}, cryptographicFunctions);
|
|
142
144
|
}
|
|
143
145
|
exports.getNode = getNode;
|
|
146
|
+
/**
|
|
147
|
+
* Validate the key of a state object.
|
|
148
|
+
*
|
|
149
|
+
* @param key - The key to validate.
|
|
150
|
+
* @returns `true` if the key is valid, `false` otherwise.
|
|
151
|
+
*/
|
|
152
|
+
function isValidStateKey(key) {
|
|
153
|
+
if (key === undefined) {
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
return key.split('.').every((part) => part.length > 0);
|
|
157
|
+
}
|
|
158
|
+
exports.isValidStateKey = isValidStateKey;
|
|
159
|
+
exports.StateKeyStruct = (0, superstruct_1.refine)((0, superstruct_1.string)(), 'state key', (value) => {
|
|
160
|
+
if (!isValidStateKey(value)) {
|
|
161
|
+
return 'Invalid state key. Each part of the key must be non-empty.';
|
|
162
|
+
}
|
|
163
|
+
return true;
|
|
164
|
+
});
|
|
144
165
|
//# sourceMappingURL=utils.cjs.map
|
package/dist/utils.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.cjs","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n HardenedBIP32Node,\n BIP32Node,\n SLIP10PathNode,\n SupportedCurve,\n CryptographicFunctions,\n} from '@metamask/key-tree';\nimport { SLIP10Node } from '@metamask/key-tree';\nimport type { MagicValue } from '@metamask/snaps-utils';\nimport type { Hex } from '@metamask/utils';\nimport {\n assertExhaustive,\n add0x,\n assert,\n concatBytes,\n createDataView,\n stringToBytes,\n} from '@metamask/utils';\nimport { keccak_256 as keccak256 } from '@noble/hashes/sha3';\n\nconst HARDENED_VALUE = 0x80000000;\n\n/**\n * Maps an interface with method hooks to an object, using the keys of the\n * interface, and `true` as value. This ensures that the `methodHooks` object\n * has the same values as the interface.\n */\nexport type MethodHooksObject<HooksType extends Record<string, unknown>> = {\n [Key in keyof HooksType]: true;\n};\n\n/**\n * Returns the subset of the specified `hooks` that are included in the\n * `hookNames` object. This is a Principle of Least Authority (POLA) measure\n * to ensure that each RPC method implementation only has access to the\n * API \"hooks\" it needs to do its job.\n *\n * @param hooks - The hooks to select from.\n * @param hookNames - The names of the hooks to select.\n * @returns The selected hooks.\n * @template Hooks - The hooks to select from.\n * @template HookName - The names of the hooks to select.\n */\nexport function selectHooks<\n Hooks extends Record<string, unknown>,\n HookName extends keyof Hooks,\n>(\n hooks: Hooks,\n hookNames?: Record<HookName, boolean>,\n): Pick<Hooks, HookName> | undefined {\n if (hookNames) {\n return Object.keys(hookNames).reduce<Partial<Pick<Hooks, HookName>>>(\n (hookSubset, _hookName) => {\n const hookName = _hookName as HookName;\n hookSubset[hookName] = hooks[hookName];\n return hookSubset;\n },\n {},\n ) as Pick<Hooks, HookName>;\n }\n return undefined;\n}\n\n/**\n * Get a BIP-32 derivation path array from a hash, which is compatible with\n * `@metamask/key-tree`. The hash is assumed to be 32 bytes long.\n *\n * @param hash - The hash to derive indices from.\n * @returns The derived indices as a {@link HardenedBIP32Node} array.\n */\nfunction getDerivationPathArray(hash: Uint8Array): HardenedBIP32Node[] {\n const array: HardenedBIP32Node[] = [];\n const view = createDataView(hash);\n\n for (let index = 0; index < 8; index++) {\n const uint32 = view.getUint32(index * 4);\n\n // This is essentially `index | 0x80000000`. Because JavaScript numbers are\n // signed, we use the bitwise unsigned right shift operator to ensure that\n // the result is a positive number.\n // eslint-disable-next-line no-bitwise\n const pathIndex = (uint32 | HARDENED_VALUE) >>> 0;\n array.push(`bip32:${pathIndex - HARDENED_VALUE}'` as const);\n }\n\n return array;\n}\n\ntype DeriveEntropyOptions = {\n /**\n * The input value to derive entropy from.\n */\n input: string;\n\n /**\n * An optional salt to use when deriving entropy.\n */\n salt?: string;\n\n /**\n * The mnemonic phrase to use for entropy derivation.\n */\n mnemonicPhrase: Uint8Array;\n\n /**\n * A hardened BIP-32 index, which is used to derive the root key from the\n * mnemonic phrase.\n */\n magic: MagicValue;\n\n /**\n * The cryptographic functions to use for the derivation.\n */\n cryptographicFunctions: CryptographicFunctions | undefined;\n};\n\n/**\n * Derive entropy from the given mnemonic phrase and salt.\n *\n * This is based on the reference implementation of\n * [SIP-6](https://metamask.github.io/SIPs/SIPS/sip-6).\n *\n * @param options - The options for entropy derivation.\n * @param options.input - The input value to derive entropy from.\n * @param options.salt - An optional salt to use when deriving entropy.\n * @param options.mnemonicPhrase - The mnemonic phrase to use for entropy\n * derivation.\n * @param options.magic - A hardened BIP-32 index, which is used to derive the\n * root key from the mnemonic phrase.\n * @param options.cryptographicFunctions - The cryptographic functions to use\n * for the derivation.\n * @returns The derived entropy.\n */\nexport async function deriveEntropy({\n input,\n salt = '',\n mnemonicPhrase,\n magic,\n cryptographicFunctions,\n}: DeriveEntropyOptions): Promise<Hex> {\n const inputBytes = stringToBytes(input);\n const saltBytes = stringToBytes(salt);\n\n // Get the derivation path from the snap ID.\n const hash = keccak256(concatBytes([inputBytes, keccak256(saltBytes)]));\n const computedDerivationPath = getDerivationPathArray(hash);\n\n // Derive the private key using BIP-32.\n const { privateKey } = await SLIP10Node.fromDerivationPath(\n {\n derivationPath: [\n mnemonicPhrase,\n `bip32:${magic}`,\n ...computedDerivationPath,\n ],\n curve: 'secp256k1',\n },\n cryptographicFunctions,\n );\n\n // This should never happen, but this keeps TypeScript happy.\n assert(privateKey, 'Failed to derive the entropy.');\n\n return add0x(privateKey);\n}\n\n/**\n * Get the path prefix to use for key derivation in `key-tree`. This assumes the\n * following:\n *\n * - The Secp256k1 curve always uses the BIP-32 specification.\n * - The Ed25519 curve always uses the SLIP-10 specification.\n * - The BIP-32-Ed25519 curve always uses the CIP-3 specification.\n *\n * While this does not matter in most situations (no known case at the time of\n * writing), `key-tree` requires a specific specification to be used.\n *\n * @param curve - The curve to get the path prefix for. The curve is NOT\n * validated by this function.\n * @returns The path prefix, i.e., `bip32` or `slip10`.\n */\nexport function getPathPrefix(\n curve: SupportedCurve,\n): 'bip32' | 'slip10' | 'cip3' {\n switch (curve) {\n case 'secp256k1':\n return 'bip32';\n case 'ed25519':\n return 'slip10';\n case 'ed25519Bip32':\n return 'cip3';\n default:\n return assertExhaustive(curve);\n }\n}\n\ntype GetNodeArgs = {\n curve: SupportedCurve;\n secretRecoveryPhrase: Uint8Array;\n path: string[];\n cryptographicFunctions: CryptographicFunctions | undefined;\n};\n\n/**\n * Get a `key-tree`-compatible node.\n *\n * Note: This function assumes that all the parameters have been validated\n * beforehand.\n *\n * @param options - The derivation options.\n * @param options.curve - The curve to use for derivation.\n * @param options.secretRecoveryPhrase - The secret recovery phrase to use for\n * derivation.\n * @param options.path - The derivation path to use as array, starting with an\n * \"m\" as the first item.\n * @param options.cryptographicFunctions - The cryptographic functions to use\n * for the node.\n * @returns The `key-tree` SLIP-10 node.\n */\nexport async function getNode({\n curve,\n secretRecoveryPhrase,\n path,\n cryptographicFunctions,\n}: GetNodeArgs) {\n const prefix = getPathPrefix(curve);\n\n return await SLIP10Node.fromDerivationPath(\n {\n curve,\n derivationPath: [\n secretRecoveryPhrase,\n ...(path.slice(1).map((index) => `${prefix}:${index}`) as\n | BIP32Node[]\n | SLIP10PathNode[]),\n ],\n },\n cryptographicFunctions,\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"utils.cjs","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n HardenedBIP32Node,\n BIP32Node,\n SLIP10PathNode,\n SupportedCurve,\n CryptographicFunctions,\n} from '@metamask/key-tree';\nimport { SLIP10Node } from '@metamask/key-tree';\nimport type { MagicValue } from '@metamask/snaps-utils';\nimport { refine, string } from '@metamask/superstruct';\nimport type { Hex } from '@metamask/utils';\nimport {\n assertExhaustive,\n add0x,\n assert,\n concatBytes,\n createDataView,\n stringToBytes,\n} from '@metamask/utils';\nimport { keccak_256 as keccak256 } from '@noble/hashes/sha3';\n\nconst HARDENED_VALUE = 0x80000000;\n\nexport const FORBIDDEN_KEYS = ['constructor', '__proto__', 'prototype'];\n\n/**\n * Maps an interface with method hooks to an object, using the keys of the\n * interface, and `true` as value. This ensures that the `methodHooks` object\n * has the same values as the interface.\n */\nexport type MethodHooksObject<HooksType extends Record<string, unknown>> = {\n [Key in keyof HooksType]: true;\n};\n\n/**\n * Returns the subset of the specified `hooks` that are included in the\n * `hookNames` object. This is a Principle of Least Authority (POLA) measure\n * to ensure that each RPC method implementation only has access to the\n * API \"hooks\" it needs to do its job.\n *\n * @param hooks - The hooks to select from.\n * @param hookNames - The names of the hooks to select.\n * @returns The selected hooks.\n * @template Hooks - The hooks to select from.\n * @template HookName - The names of the hooks to select.\n */\nexport function selectHooks<\n Hooks extends Record<string, unknown>,\n HookName extends keyof Hooks,\n>(\n hooks: Hooks,\n hookNames?: Record<HookName, boolean>,\n): Pick<Hooks, HookName> | undefined {\n if (hookNames) {\n return Object.keys(hookNames).reduce<Partial<Pick<Hooks, HookName>>>(\n (hookSubset, _hookName) => {\n const hookName = _hookName as HookName;\n hookSubset[hookName] = hooks[hookName];\n return hookSubset;\n },\n {},\n ) as Pick<Hooks, HookName>;\n }\n return undefined;\n}\n\n/**\n * Get a BIP-32 derivation path array from a hash, which is compatible with\n * `@metamask/key-tree`. The hash is assumed to be 32 bytes long.\n *\n * @param hash - The hash to derive indices from.\n * @returns The derived indices as a {@link HardenedBIP32Node} array.\n */\nfunction getDerivationPathArray(hash: Uint8Array): HardenedBIP32Node[] {\n const array: HardenedBIP32Node[] = [];\n const view = createDataView(hash);\n\n for (let index = 0; index < 8; index++) {\n const uint32 = view.getUint32(index * 4);\n\n // This is essentially `index | 0x80000000`. Because JavaScript numbers are\n // signed, we use the bitwise unsigned right shift operator to ensure that\n // the result is a positive number.\n // eslint-disable-next-line no-bitwise\n const pathIndex = (uint32 | HARDENED_VALUE) >>> 0;\n array.push(`bip32:${pathIndex - HARDENED_VALUE}'` as const);\n }\n\n return array;\n}\n\ntype DeriveEntropyOptions = {\n /**\n * The input value to derive entropy from.\n */\n input: string;\n\n /**\n * An optional salt to use when deriving entropy.\n */\n salt?: string;\n\n /**\n * The mnemonic phrase to use for entropy derivation.\n */\n mnemonicPhrase: Uint8Array;\n\n /**\n * A hardened BIP-32 index, which is used to derive the root key from the\n * mnemonic phrase.\n */\n magic: MagicValue;\n\n /**\n * The cryptographic functions to use for the derivation.\n */\n cryptographicFunctions: CryptographicFunctions | undefined;\n};\n\n/**\n * Derive entropy from the given mnemonic phrase and salt.\n *\n * This is based on the reference implementation of\n * [SIP-6](https://metamask.github.io/SIPs/SIPS/sip-6).\n *\n * @param options - The options for entropy derivation.\n * @param options.input - The input value to derive entropy from.\n * @param options.salt - An optional salt to use when deriving entropy.\n * @param options.mnemonicPhrase - The mnemonic phrase to use for entropy\n * derivation.\n * @param options.magic - A hardened BIP-32 index, which is used to derive the\n * root key from the mnemonic phrase.\n * @param options.cryptographicFunctions - The cryptographic functions to use\n * for the derivation.\n * @returns The derived entropy.\n */\nexport async function deriveEntropy({\n input,\n salt = '',\n mnemonicPhrase,\n magic,\n cryptographicFunctions,\n}: DeriveEntropyOptions): Promise<Hex> {\n const inputBytes = stringToBytes(input);\n const saltBytes = stringToBytes(salt);\n\n // Get the derivation path from the snap ID.\n const hash = keccak256(concatBytes([inputBytes, keccak256(saltBytes)]));\n const computedDerivationPath = getDerivationPathArray(hash);\n\n // Derive the private key using BIP-32.\n const { privateKey } = await SLIP10Node.fromDerivationPath(\n {\n derivationPath: [\n mnemonicPhrase,\n `bip32:${magic}`,\n ...computedDerivationPath,\n ],\n curve: 'secp256k1',\n },\n cryptographicFunctions,\n );\n\n // This should never happen, but this keeps TypeScript happy.\n assert(privateKey, 'Failed to derive the entropy.');\n\n return add0x(privateKey);\n}\n\n/**\n * Get the path prefix to use for key derivation in `key-tree`. This assumes the\n * following:\n *\n * - The Secp256k1 curve always uses the BIP-32 specification.\n * - The Ed25519 curve always uses the SLIP-10 specification.\n * - The BIP-32-Ed25519 curve always uses the CIP-3 specification.\n *\n * While this does not matter in most situations (no known case at the time of\n * writing), `key-tree` requires a specific specification to be used.\n *\n * @param curve - The curve to get the path prefix for. The curve is NOT\n * validated by this function.\n * @returns The path prefix, i.e., `bip32` or `slip10`.\n */\nexport function getPathPrefix(\n curve: SupportedCurve,\n): 'bip32' | 'slip10' | 'cip3' {\n switch (curve) {\n case 'secp256k1':\n return 'bip32';\n case 'ed25519':\n return 'slip10';\n case 'ed25519Bip32':\n return 'cip3';\n default:\n return assertExhaustive(curve);\n }\n}\n\ntype GetNodeArgs = {\n curve: SupportedCurve;\n secretRecoveryPhrase: Uint8Array;\n path: string[];\n cryptographicFunctions: CryptographicFunctions | undefined;\n};\n\n/**\n * Get a `key-tree`-compatible node.\n *\n * Note: This function assumes that all the parameters have been validated\n * beforehand.\n *\n * @param options - The derivation options.\n * @param options.curve - The curve to use for derivation.\n * @param options.secretRecoveryPhrase - The secret recovery phrase to use for\n * derivation.\n * @param options.path - The derivation path to use as array, starting with an\n * \"m\" as the first item.\n * @param options.cryptographicFunctions - The cryptographic functions to use\n * for the node.\n * @returns The `key-tree` SLIP-10 node.\n */\nexport async function getNode({\n curve,\n secretRecoveryPhrase,\n path,\n cryptographicFunctions,\n}: GetNodeArgs) {\n const prefix = getPathPrefix(curve);\n\n return await SLIP10Node.fromDerivationPath(\n {\n curve,\n derivationPath: [\n secretRecoveryPhrase,\n ...(path.slice(1).map((index) => `${prefix}:${index}`) as\n | BIP32Node[]\n | SLIP10PathNode[]),\n ],\n },\n cryptographicFunctions,\n );\n}\n\n/**\n * Validate the key of a state object.\n *\n * @param key - The key to validate.\n * @returns `true` if the key is valid, `false` otherwise.\n */\nexport function isValidStateKey(key: string | undefined) {\n if (key === undefined) {\n return true;\n }\n\n return key.split('.').every((part) => part.length > 0);\n}\n\nexport const StateKeyStruct = refine(string(), 'state key', (value) => {\n if (!isValidStateKey(value)) {\n return 'Invalid state key. Each part of the key must be non-empty.';\n }\n\n return true;\n});\n"]}
|
package/dist/utils.d.cts
CHANGED
|
@@ -2,6 +2,7 @@ import type { SupportedCurve, CryptographicFunctions } from "@metamask/key-tree"
|
|
|
2
2
|
import { SLIP10Node } from "@metamask/key-tree";
|
|
3
3
|
import type { MagicValue } from "@metamask/snaps-utils";
|
|
4
4
|
import type { Hex } from "@metamask/utils";
|
|
5
|
+
export declare const FORBIDDEN_KEYS: string[];
|
|
5
6
|
/**
|
|
6
7
|
* Maps an interface with method hooks to an object, using the keys of the
|
|
7
8
|
* interface, and `true` as value. This ensures that the `methodHooks` object
|
|
@@ -103,5 +104,13 @@ type GetNodeArgs = {
|
|
|
103
104
|
* @returns The `key-tree` SLIP-10 node.
|
|
104
105
|
*/
|
|
105
106
|
export declare function getNode({ curve, secretRecoveryPhrase, path, cryptographicFunctions, }: GetNodeArgs): Promise<SLIP10Node>;
|
|
107
|
+
/**
|
|
108
|
+
* Validate the key of a state object.
|
|
109
|
+
*
|
|
110
|
+
* @param key - The key to validate.
|
|
111
|
+
* @returns `true` if the key is valid, `false` otherwise.
|
|
112
|
+
*/
|
|
113
|
+
export declare function isValidStateKey(key: string | undefined): boolean;
|
|
114
|
+
export declare const StateKeyStruct: import("@metamask/superstruct").Struct<string, null>;
|
|
106
115
|
export {};
|
|
107
116
|
//# sourceMappingURL=utils.d.cts.map
|
package/dist/utils.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.cts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAIV,cAAc,EACd,sBAAsB,EACvB,2BAA2B;AAC5B,OAAO,EAAE,UAAU,EAAE,2BAA2B;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,8BAA8B;
|
|
1
|
+
{"version":3,"file":"utils.d.cts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAIV,cAAc,EACd,sBAAsB,EACvB,2BAA2B;AAC5B,OAAO,EAAE,UAAU,EAAE,2BAA2B;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,8BAA8B;AAExD,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAa3C,eAAO,MAAM,cAAc,UAA4C,CAAC;AAExE;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,CAAC,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;KACxE,GAAG,IAAI,MAAM,SAAS,GAAG,IAAI;CAC/B,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CACzB,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,QAAQ,SAAS,MAAM,KAAK,EAE5B,KAAK,EAAE,KAAK,EACZ,SAAS,CAAC,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,GACpC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,SAAS,CAYnC;AA2BD,KAAK,oBAAoB,GAAG;IAC1B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,cAAc,EAAE,UAAU,CAAC;IAE3B;;;OAGG;IACH,KAAK,EAAE,UAAU,CAAC;IAElB;;OAEG;IACH,sBAAsB,EAAE,sBAAsB,GAAG,SAAS,CAAC;CAC5D,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,aAAa,CAAC,EAClC,KAAK,EACL,IAAS,EACT,cAAc,EACd,KAAK,EACL,sBAAsB,GACvB,EAAE,oBAAoB,GAAG,OAAO,CAAC,GAAG,CAAC,CAyBrC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,cAAc,GACpB,OAAO,GAAG,QAAQ,GAAG,MAAM,CAW7B;AAED,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,cAAc,CAAC;IACtB,oBAAoB,EAAE,UAAU,CAAC;IACjC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,sBAAsB,EAAE,sBAAsB,GAAG,SAAS,CAAC;CAC5D,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,OAAO,CAAC,EAC5B,KAAK,EACL,oBAAoB,EACpB,IAAI,EACJ,sBAAsB,GACvB,EAAE,WAAW,uBAeb;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,WAMtD;AAED,eAAO,MAAM,cAAc,sDAMzB,CAAC"}
|
package/dist/utils.d.mts
CHANGED
|
@@ -2,6 +2,7 @@ import type { SupportedCurve, CryptographicFunctions } from "@metamask/key-tree"
|
|
|
2
2
|
import { SLIP10Node } from "@metamask/key-tree";
|
|
3
3
|
import type { MagicValue } from "@metamask/snaps-utils";
|
|
4
4
|
import type { Hex } from "@metamask/utils";
|
|
5
|
+
export declare const FORBIDDEN_KEYS: string[];
|
|
5
6
|
/**
|
|
6
7
|
* Maps an interface with method hooks to an object, using the keys of the
|
|
7
8
|
* interface, and `true` as value. This ensures that the `methodHooks` object
|
|
@@ -103,5 +104,13 @@ type GetNodeArgs = {
|
|
|
103
104
|
* @returns The `key-tree` SLIP-10 node.
|
|
104
105
|
*/
|
|
105
106
|
export declare function getNode({ curve, secretRecoveryPhrase, path, cryptographicFunctions, }: GetNodeArgs): Promise<SLIP10Node>;
|
|
107
|
+
/**
|
|
108
|
+
* Validate the key of a state object.
|
|
109
|
+
*
|
|
110
|
+
* @param key - The key to validate.
|
|
111
|
+
* @returns `true` if the key is valid, `false` otherwise.
|
|
112
|
+
*/
|
|
113
|
+
export declare function isValidStateKey(key: string | undefined): boolean;
|
|
114
|
+
export declare const StateKeyStruct: import("@metamask/superstruct").Struct<string, null>;
|
|
106
115
|
export {};
|
|
107
116
|
//# sourceMappingURL=utils.d.mts.map
|