@metamask/snaps-rpc-methods 11.8.0 → 11.9.1

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.
Files changed (102) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/dist/endowments/cronjob.cjs +8 -0
  3. package/dist/endowments/cronjob.cjs.map +1 -1
  4. package/dist/endowments/cronjob.d.cts.map +1 -1
  5. package/dist/endowments/cronjob.d.mts.map +1 -1
  6. package/dist/endowments/cronjob.mjs +9 -1
  7. package/dist/endowments/cronjob.mjs.map +1 -1
  8. package/dist/permitted/cancelBackgroundEvent.cjs +69 -0
  9. package/dist/permitted/cancelBackgroundEvent.cjs.map +1 -0
  10. package/dist/permitted/cancelBackgroundEvent.d.cts +16 -0
  11. package/dist/permitted/cancelBackgroundEvent.d.cts.map +1 -0
  12. package/dist/permitted/cancelBackgroundEvent.d.mts +16 -0
  13. package/dist/permitted/cancelBackgroundEvent.d.mts.map +1 -0
  14. package/dist/permitted/cancelBackgroundEvent.mjs +66 -0
  15. package/dist/permitted/cancelBackgroundEvent.mjs.map +1 -0
  16. package/dist/permitted/clearState.cjs +73 -0
  17. package/dist/permitted/clearState.cjs.map +1 -0
  18. package/dist/permitted/clearState.d.cts +28 -0
  19. package/dist/permitted/clearState.d.cts.map +1 -0
  20. package/dist/permitted/clearState.d.mts +28 -0
  21. package/dist/permitted/clearState.d.mts.map +1 -0
  22. package/dist/permitted/clearState.mjs +70 -0
  23. package/dist/permitted/clearState.mjs.map +1 -0
  24. package/dist/permitted/createInterface.d.cts +2 -0
  25. package/dist/permitted/createInterface.d.cts.map +1 -1
  26. package/dist/permitted/createInterface.d.mts +2 -0
  27. package/dist/permitted/createInterface.d.mts.map +1 -1
  28. package/dist/permitted/getBackgroundEvents.cjs +42 -0
  29. package/dist/permitted/getBackgroundEvents.cjs.map +1 -0
  30. package/dist/permitted/getBackgroundEvents.d.cts +8 -0
  31. package/dist/permitted/getBackgroundEvents.d.cts.map +1 -0
  32. package/dist/permitted/getBackgroundEvents.d.mts +8 -0
  33. package/dist/permitted/getBackgroundEvents.d.mts.map +1 -0
  34. package/dist/permitted/getBackgroundEvents.mjs +39 -0
  35. package/dist/permitted/getBackgroundEvents.mjs.map +1 -0
  36. package/dist/permitted/getState.cjs +118 -0
  37. package/dist/permitted/getState.cjs.map +1 -0
  38. package/dist/permitted/getState.d.cts +53 -0
  39. package/dist/permitted/getState.d.cts.map +1 -0
  40. package/dist/permitted/getState.d.mts +53 -0
  41. package/dist/permitted/getState.d.mts.map +1 -0
  42. package/dist/permitted/getState.mjs +114 -0
  43. package/dist/permitted/getState.mjs.map +1 -0
  44. package/dist/permitted/handlers.cjs +12 -0
  45. package/dist/permitted/handlers.cjs.map +1 -1
  46. package/dist/permitted/handlers.d.cts +8 -2
  47. package/dist/permitted/handlers.d.cts.map +1 -1
  48. package/dist/permitted/handlers.d.mts +8 -2
  49. package/dist/permitted/handlers.d.mts.map +1 -1
  50. package/dist/permitted/handlers.mjs +12 -0
  51. package/dist/permitted/handlers.mjs.map +1 -1
  52. package/dist/permitted/index.cjs.map +1 -1
  53. package/dist/permitted/index.d.cts +7 -1
  54. package/dist/permitted/index.d.cts.map +1 -1
  55. package/dist/permitted/index.d.mts +7 -1
  56. package/dist/permitted/index.d.mts.map +1 -1
  57. package/dist/permitted/index.mjs.map +1 -1
  58. package/dist/permitted/scheduleBackgroundEvent.cjs +122 -0
  59. package/dist/permitted/scheduleBackgroundEvent.cjs.map +1 -0
  60. package/dist/permitted/scheduleBackgroundEvent.d.cts +33 -0
  61. package/dist/permitted/scheduleBackgroundEvent.d.cts.map +1 -0
  62. package/dist/permitted/scheduleBackgroundEvent.d.mts +33 -0
  63. package/dist/permitted/scheduleBackgroundEvent.d.mts.map +1 -0
  64. package/dist/permitted/scheduleBackgroundEvent.mjs +119 -0
  65. package/dist/permitted/scheduleBackgroundEvent.mjs.map +1 -0
  66. package/dist/permitted/setState.cjs +160 -0
  67. package/dist/permitted/setState.cjs.map +1 -0
  68. package/dist/permitted/setState.d.cts +65 -0
  69. package/dist/permitted/setState.d.cts.map +1 -0
  70. package/dist/permitted/setState.d.mts +65 -0
  71. package/dist/permitted/setState.d.mts.map +1 -0
  72. package/dist/permitted/setState.mjs +156 -0
  73. package/dist/permitted/setState.mjs.map +1 -0
  74. package/dist/permitted/updateInterface.d.cts +2 -0
  75. package/dist/permitted/updateInterface.d.cts.map +1 -1
  76. package/dist/permitted/updateInterface.d.mts +2 -0
  77. package/dist/permitted/updateInterface.d.mts.map +1 -1
  78. package/dist/restricted/dialog.d.cts +4 -0
  79. package/dist/restricted/dialog.d.cts.map +1 -1
  80. package/dist/restricted/dialog.d.mts +4 -0
  81. package/dist/restricted/dialog.d.mts.map +1 -1
  82. package/dist/restricted/manageState.cjs +4 -13
  83. package/dist/restricted/manageState.cjs.map +1 -1
  84. package/dist/restricted/manageState.d.cts +1 -1
  85. package/dist/restricted/manageState.d.cts.map +1 -1
  86. package/dist/restricted/manageState.d.mts +1 -1
  87. package/dist/restricted/manageState.d.mts.map +1 -1
  88. package/dist/restricted/manageState.mjs +4 -13
  89. package/dist/restricted/manageState.mjs.map +1 -1
  90. package/dist/restricted/notify.d.cts +3 -0
  91. package/dist/restricted/notify.d.cts.map +1 -1
  92. package/dist/restricted/notify.d.mts +3 -0
  93. package/dist/restricted/notify.d.mts.map +1 -1
  94. package/dist/utils.cjs +22 -1
  95. package/dist/utils.cjs.map +1 -1
  96. package/dist/utils.d.cts +9 -0
  97. package/dist/utils.d.cts.map +1 -1
  98. package/dist/utils.d.mts +9 -0
  99. package/dist/utils.d.mts.map +1 -1
  100. package/dist/utils.mjs +20 -0
  101. package/dist/utils.mjs.map +1 -1
  102. package/package.json +11 -9
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduleBackgroundEvent.mjs","sourceRoot":"","sources":["../../src/permitted/scheduleBackgroundEvent.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 {\n selectiveUnion,\n type JsonRpcRequest,\n type ScheduleBackgroundEventParams,\n type ScheduleBackgroundEventResult,\n} from '@metamask/snaps-sdk';\nimport type { CronjobRpcRequest } from '@metamask/snaps-utils';\nimport {\n CronjobRpcRequestStruct,\n type InferMatching,\n} from '@metamask/snaps-utils';\nimport {\n StructError,\n create,\n object,\n refine,\n string,\n} from '@metamask/superstruct';\nimport {\n assert,\n hasProperty,\n type PendingJsonRpcResponse,\n} from '@metamask/utils';\nimport { DateTime, Duration } from 'luxon';\n\nimport { SnapEndowments } from '../endowments';\nimport type { MethodHooksObject } from '../utils';\n\nconst methodName = 'snap_scheduleBackgroundEvent';\n\nconst hookNames: MethodHooksObject<ScheduleBackgroundEventMethodHooks> = {\n scheduleBackgroundEvent: true,\n hasPermission: true,\n};\n\ntype ScheduleBackgroundEventHookParams = {\n date: string;\n request: CronjobRpcRequest;\n};\n\nexport type ScheduleBackgroundEventMethodHooks = {\n scheduleBackgroundEvent: (\n snapEvent: ScheduleBackgroundEventHookParams,\n ) => string;\n\n hasPermission: (permissionName: string) => boolean;\n};\n\nexport const scheduleBackgroundEventHandler: PermittedHandlerExport<\n ScheduleBackgroundEventMethodHooks,\n ScheduleBackgroundEventParameters,\n ScheduleBackgroundEventResult\n> = {\n methodNames: [methodName],\n implementation: getScheduleBackgroundEventImplementation,\n hookNames,\n};\n\nconst offsetRegex = /Z|([+-]\\d{2}:?\\d{2})$/u;\n\nconst ScheduleBackgroundEventParametersWithDateStruct = object({\n date: refine(string(), 'date', (val) => {\n const date = DateTime.fromISO(val);\n if (date.isValid) {\n // Luxon doesn't have a reliable way to check if timezone info was not provided\n if (!offsetRegex.test(val)) {\n return 'ISO 8601 date must have timezone information';\n }\n return true;\n }\n return 'Not a valid ISO 8601 date';\n }),\n request: CronjobRpcRequestStruct,\n});\n\nconst ScheduleBackgroundEventParametersWithDurationStruct = object({\n duration: refine(string(), 'duration', (val) => {\n const duration = Duration.fromISO(val);\n if (!duration.isValid) {\n return 'Not a valid ISO 8601 duration';\n }\n return true;\n }),\n request: CronjobRpcRequestStruct,\n});\n\nconst ScheduleBackgroundEventParametersStruct = selectiveUnion((val) => {\n if (hasProperty(val, 'date')) {\n return ScheduleBackgroundEventParametersWithDateStruct;\n }\n return ScheduleBackgroundEventParametersWithDurationStruct;\n});\n\nexport type ScheduleBackgroundEventParameters = InferMatching<\n typeof ScheduleBackgroundEventParametersStruct,\n ScheduleBackgroundEventParams\n>;\n\n/**\n * Generates a `DateTime` object based on if a duration or date is provided.\n *\n * @param params - The validated params from the `snap_scheduleBackgroundEvent` call.\n * @returns A `DateTime` object.\n */\nfunction getStartDate(params: ScheduleBackgroundEventParams) {\n if ('duration' in params) {\n return DateTime.fromJSDate(new Date())\n .toUTC()\n .plus(Duration.fromISO(params.duration));\n }\n\n return DateTime.fromISO(params.date, { setZone: true });\n}\n\n/**\n * The `snap_scheduleBackgroundEvent` method implementation.\n *\n * @param req - The JSON-RPC request object.\n * @param res - 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.scheduleBackgroundEvent - The function to schedule a background event.\n * @param hooks.hasPermission - The function to check if a snap has the `endowment:cronjob` permission.\n * @returns An id representing the background event.\n */\nasync function getScheduleBackgroundEventImplementation(\n req: JsonRpcRequest<ScheduleBackgroundEventParameters>,\n res: PendingJsonRpcResponse<ScheduleBackgroundEventResult>,\n _next: unknown,\n end: JsonRpcEngineEndCallback,\n {\n scheduleBackgroundEvent,\n hasPermission,\n }: ScheduleBackgroundEventMethodHooks,\n): Promise<void> {\n const { params } = req;\n\n if (!hasPermission(SnapEndowments.Cronjob)) {\n return end(providerErrors.unauthorized());\n }\n\n try {\n const validatedParams = getValidatedParams(params);\n\n const { request } = validatedParams;\n\n const date = getStartDate(validatedParams);\n\n // Make sure any millisecond precision is removed.\n const truncatedDate = date.startOf('second').toISO({\n suppressMilliseconds: true,\n });\n\n assert(truncatedDate);\n\n const id = scheduleBackgroundEvent({ date: truncatedDate, request });\n res.result = id;\n } catch (error) {\n return end(error);\n }\n\n return end();\n}\n\n/**\n * Validate the scheduleBackgroundEvent method `params` and returns them cast to the correct\n * type. Throws if validation fails.\n *\n * @param params - The unvalidated params object from the method request.\n * @returns The validated resolveInterface method parameter object.\n */\nfunction getValidatedParams(\n params: unknown,\n): ScheduleBackgroundEventParameters {\n try {\n return create(params, ScheduleBackgroundEventParametersStruct);\n } catch (error) {\n if (error instanceof StructError) {\n throw rpcErrors.invalidParams({\n message: `Invalid params: ${error.message}.`,\n });\n }\n /* istanbul ignore next */\n throw rpcErrors.internal();\n }\n}\n"]}
@@ -0,0 +1,160 @@
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
+ const size = (0, utils_1.getJsonSize)(newState);
60
+ if (size > manageState_1.STORAGE_SIZE_LIMIT) {
61
+ throw rpc_errors_1.rpcErrors.invalidParams({
62
+ message: `Invalid params: The new state must not exceed ${manageState_1.STORAGE_SIZE_LIMIT / 1000000} MB in size.`,
63
+ });
64
+ }
65
+ await updateSnapState(newState, encrypted);
66
+ response.result = null;
67
+ }
68
+ catch (error) {
69
+ return end(error);
70
+ }
71
+ return end();
72
+ }
73
+ /**
74
+ * Validate the parameters of the `snap_setState` method.
75
+ *
76
+ * @param params - The parameters to validate.
77
+ * @returns The validated parameters.
78
+ */
79
+ function getValidatedParams(params) {
80
+ try {
81
+ return (0, superstruct_1.create)(params, SetStateParametersStruct);
82
+ }
83
+ catch (error) {
84
+ if (error instanceof superstruct_1.StructError) {
85
+ throw rpc_errors_1.rpcErrors.invalidParams({
86
+ message: `Invalid params: ${error.message}.`,
87
+ });
88
+ }
89
+ /* istanbul ignore next */
90
+ throw rpc_errors_1.rpcErrors.internal();
91
+ }
92
+ }
93
+ /**
94
+ * Get the new state of the Snap.
95
+ *
96
+ * If the key is `undefined`, the value is expected to be an object. In this
97
+ * case, the value is returned as the new state.
98
+ *
99
+ * If the key is not `undefined`, the value is set in the state at the key. If
100
+ * the key does not exist, it is created (and any missing intermediate keys are
101
+ * created as well).
102
+ *
103
+ * @param key - The key to set.
104
+ * @param value - The value to set the key to.
105
+ * @param encrypted - Whether the state is encrypted.
106
+ * @param getSnapState - The `getSnapState` hook.
107
+ * @returns The new state of the Snap.
108
+ */
109
+ async function getNewState(key, value, encrypted, getSnapState) {
110
+ if (key === undefined) {
111
+ (0, utils_1.assert)((0, utils_1.isObject)(value));
112
+ return value;
113
+ }
114
+ const state = await getSnapState(encrypted);
115
+ return set(state, key, value);
116
+ }
117
+ /**
118
+ * Set the value of a key in an object. The key may contain Lodash-style path
119
+ * syntax, e.g., `a.b.c` (with the exception of array syntax). If the key does
120
+ * not exist, it is created (and any missing intermediate keys are created as
121
+ * well).
122
+ *
123
+ * This is a simplified version of Lodash's `set` function, but Lodash doesn't
124
+ * seem to be maintained anymore, so we're using our own implementation.
125
+ *
126
+ * @param object - The object to get the key from.
127
+ * @param key - The key to set.
128
+ * @param value - The value to set the key to.
129
+ * @returns The new object with the key set to the value.
130
+ */
131
+ function set(
132
+ // eslint-disable-next-line @typescript-eslint/default-param-last
133
+ object, key, value) {
134
+ const keys = key.split('.');
135
+ const requiredObject = object ?? {};
136
+ let currentObject = requiredObject;
137
+ for (let i = 0; i < keys.length; i++) {
138
+ const currentKey = keys[i];
139
+ if (utils_2.FORBIDDEN_KEYS.includes(currentKey)) {
140
+ throw rpc_errors_1.rpcErrors.invalidParams('Invalid params: Key contains forbidden characters.');
141
+ }
142
+ if (i === keys.length - 1) {
143
+ currentObject[currentKey] = value;
144
+ return requiredObject;
145
+ }
146
+ if (!(0, utils_1.hasProperty)(currentObject, currentKey) ||
147
+ currentObject[currentKey] === null) {
148
+ currentObject[currentKey] = {};
149
+ }
150
+ else if (!(0, utils_1.isObject)(currentObject[currentKey])) {
151
+ throw rpc_errors_1.rpcErrors.invalidParams('Invalid params: Cannot overwrite non-object value.');
152
+ }
153
+ currentObject = currentObject[currentKey];
154
+ }
155
+ // This should never be reached.
156
+ /* istanbul ignore next */
157
+ throw new Error('Unexpected error while setting the state.');
158
+ }
159
+ exports.set = set;
160
+ //# 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 getJsonSize,\n hasProperty,\n isObject,\n assert,\n JsonStruct,\n type Json,\n} from '@metamask/utils';\n\nimport {\n manageStateBuilder,\n STORAGE_SIZE_LIMIT,\n} 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\n const size = getJsonSize(newState);\n if (size > STORAGE_SIZE_LIMIT) {\n throw rpcErrors.invalidParams({\n message: `Invalid params: The new state must not exceed ${\n STORAGE_SIZE_LIMIT / 1_000_000\n } MB in size.`,\n });\n }\n\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,EAML,KAAK,IAAI,EACV,wBAAwB;AAgBzB;;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;AA4HF;;;;;;;;;;;;;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,EAML,KAAK,IAAI,EACV,wBAAwB;AAgBzB;;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;AA4HF;;;;;;;;;;;;;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,156 @@
1
+ import { providerErrors, rpcErrors } from "@metamask/rpc-errors";
2
+ import { boolean, create, object as objectStruct, optional, StructError } from "@metamask/superstruct";
3
+ import { getJsonSize, hasProperty, isObject, assert, JsonStruct } from "@metamask/utils";
4
+ import { manageStateBuilder, STORAGE_SIZE_LIMIT } 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
+ const size = getJsonSize(newState);
57
+ if (size > STORAGE_SIZE_LIMIT) {
58
+ throw rpcErrors.invalidParams({
59
+ message: `Invalid params: The new state must not exceed ${STORAGE_SIZE_LIMIT / 1000000} MB in size.`,
60
+ });
61
+ }
62
+ await updateSnapState(newState, encrypted);
63
+ response.result = null;
64
+ }
65
+ catch (error) {
66
+ return end(error);
67
+ }
68
+ return end();
69
+ }
70
+ /**
71
+ * Validate the parameters of the `snap_setState` method.
72
+ *
73
+ * @param params - The parameters to validate.
74
+ * @returns The validated parameters.
75
+ */
76
+ function getValidatedParams(params) {
77
+ try {
78
+ return create(params, SetStateParametersStruct);
79
+ }
80
+ catch (error) {
81
+ if (error instanceof StructError) {
82
+ throw rpcErrors.invalidParams({
83
+ message: `Invalid params: ${error.message}.`,
84
+ });
85
+ }
86
+ /* istanbul ignore next */
87
+ throw rpcErrors.internal();
88
+ }
89
+ }
90
+ /**
91
+ * Get the new state of the Snap.
92
+ *
93
+ * If the key is `undefined`, the value is expected to be an object. In this
94
+ * case, the value is returned as the new state.
95
+ *
96
+ * If the key is not `undefined`, the value is set in the state at the key. If
97
+ * the key does not exist, it is created (and any missing intermediate keys are
98
+ * created as well).
99
+ *
100
+ * @param key - The key to set.
101
+ * @param value - The value to set the key to.
102
+ * @param encrypted - Whether the state is encrypted.
103
+ * @param getSnapState - The `getSnapState` hook.
104
+ * @returns The new state of the Snap.
105
+ */
106
+ async function getNewState(key, value, encrypted, getSnapState) {
107
+ if (key === undefined) {
108
+ assert(isObject(value));
109
+ return value;
110
+ }
111
+ const state = await getSnapState(encrypted);
112
+ return set(state, key, value);
113
+ }
114
+ /**
115
+ * Set the value of a key in an object. The key may contain Lodash-style path
116
+ * syntax, e.g., `a.b.c` (with the exception of array syntax). If the key does
117
+ * not exist, it is created (and any missing intermediate keys are created as
118
+ * well).
119
+ *
120
+ * This is a simplified version of Lodash's `set` function, but Lodash doesn't
121
+ * seem to be maintained anymore, so we're using our own implementation.
122
+ *
123
+ * @param object - The object to get the key from.
124
+ * @param key - The key to set.
125
+ * @param value - The value to set the key to.
126
+ * @returns The new object with the key set to the value.
127
+ */
128
+ export function set(
129
+ // eslint-disable-next-line @typescript-eslint/default-param-last
130
+ object, key, value) {
131
+ const keys = key.split('.');
132
+ const requiredObject = object ?? {};
133
+ let currentObject = requiredObject;
134
+ for (let i = 0; i < keys.length; i++) {
135
+ const currentKey = keys[i];
136
+ if (FORBIDDEN_KEYS.includes(currentKey)) {
137
+ throw rpcErrors.invalidParams('Invalid params: Key contains forbidden characters.');
138
+ }
139
+ if (i === keys.length - 1) {
140
+ currentObject[currentKey] = value;
141
+ return requiredObject;
142
+ }
143
+ if (!hasProperty(currentObject, currentKey) ||
144
+ currentObject[currentKey] === null) {
145
+ currentObject[currentKey] = {};
146
+ }
147
+ else if (!isObject(currentObject[currentKey])) {
148
+ throw rpcErrors.invalidParams('Invalid params: Cannot overwrite non-object value.');
149
+ }
150
+ currentObject = currentObject[currentKey];
151
+ }
152
+ // This should never be reached.
153
+ /* istanbul ignore next */
154
+ throw new Error('Unexpected error while setting the state.');
155
+ }
156
+ //# 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 getJsonSize,\n hasProperty,\n isObject,\n assert,\n JsonStruct,\n type Json,\n} from '@metamask/utils';\n\nimport {\n manageStateBuilder,\n STORAGE_SIZE_LIMIT,\n} 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\n const size = getJsonSize(newState);\n if (size > STORAGE_SIZE_LIMIT) {\n throw rpcErrors.invalidParams({\n message: `Invalid params: The new state must not exceed ${\n STORAGE_SIZE_LIMIT / 1_000_000\n } MB in size.`,\n });\n }\n\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"]}
@@ -83,6 +83,7 @@ declare const UpdateInterfaceParametersStruct: import("@metamask/superstruct").S
83
83
  } | import("@metamask/snaps-sdk/jsx").SnapElement<{
84
84
  src: string;
85
85
  alt?: string | undefined;
86
+ borderRadius?: "none" | "medium" | "full" | undefined;
86
87
  }, "Image"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
87
88
  name: string;
88
89
  value?: string | undefined;
@@ -168,6 +169,7 @@ declare const UpdateInterfaceParametersStruct: import("@metamask/superstruct").S
168
169
  } | import("@metamask/snaps-sdk/jsx").SnapElement<{
169
170
  src: string;
170
171
  alt?: string | undefined;
172
+ borderRadius?: "none" | "medium" | "full" | undefined;
171
173
  }, "Image"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
172
174
  name: string;
173
175
  value?: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"updateInterface.d.cts","sourceRoot":"","sources":["../../src/permitted/updateInterface.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,wCAAwC;AAE9E,OAAO,KAAK,EACV,qBAAqB,EACrB,qBAAqB,EAErB,kBAAkB,EAClB,gBAAgB,EACjB,4BAA4B;AAK7B,OAAO,EAAE,KAAK,aAAa,EAAE,8BAA8B;AAgB3D,MAAM,MAAM,0BAA0B,GAAG;IACvC;;;;OAIG;IACH,eAAe,EAAE,CACf,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,kBAAkB,EACtB,OAAO,CAAC,EAAE,gBAAgB,KACvB,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,sBAAsB,CACzD,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,CAKtB,CAAC;AAEF,QAAA,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAInC,CAAC;AAEH,MAAM,MAAM,yBAAyB,GAAG,aAAa,CACnD,OAAO,+BAA+B,EACtC,qBAAqB,CACtB,CAAC"}
1
+ {"version":3,"file":"updateInterface.d.cts","sourceRoot":"","sources":["../../src/permitted/updateInterface.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,wCAAwC;AAE9E,OAAO,KAAK,EACV,qBAAqB,EACrB,qBAAqB,EAErB,kBAAkB,EAClB,gBAAgB,EACjB,4BAA4B;AAK7B,OAAO,EAAE,KAAK,aAAa,EAAE,8BAA8B;AAgB3D,MAAM,MAAM,0BAA0B,GAAG;IACvC;;;;OAIG;IACH,eAAe,EAAE,CACf,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,kBAAkB,EACtB,OAAO,CAAC,EAAE,gBAAgB,KACvB,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,sBAAsB,CACzD,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,CAKtB,CAAC;AAEF,QAAA,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAInC,CAAC;AAEH,MAAM,MAAM,yBAAyB,GAAG,aAAa,CACnD,OAAO,+BAA+B,EACtC,qBAAqB,CACtB,CAAC"}
@@ -83,6 +83,7 @@ declare const UpdateInterfaceParametersStruct: import("@metamask/superstruct").S
83
83
  } | import("@metamask/snaps-sdk/jsx").SnapElement<{
84
84
  src: string;
85
85
  alt?: string | undefined;
86
+ borderRadius?: "none" | "medium" | "full" | undefined;
86
87
  }, "Image"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
87
88
  name: string;
88
89
  value?: string | undefined;
@@ -168,6 +169,7 @@ declare const UpdateInterfaceParametersStruct: import("@metamask/superstruct").S
168
169
  } | import("@metamask/snaps-sdk/jsx").SnapElement<{
169
170
  src: string;
170
171
  alt?: string | undefined;
172
+ borderRadius?: "none" | "medium" | "full" | undefined;
171
173
  }, "Image"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
172
174
  name: string;
173
175
  value?: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"updateInterface.d.mts","sourceRoot":"","sources":["../../src/permitted/updateInterface.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,wCAAwC;AAE9E,OAAO,KAAK,EACV,qBAAqB,EACrB,qBAAqB,EAErB,kBAAkB,EAClB,gBAAgB,EACjB,4BAA4B;AAK7B,OAAO,EAAE,KAAK,aAAa,EAAE,8BAA8B;AAgB3D,MAAM,MAAM,0BAA0B,GAAG;IACvC;;;;OAIG;IACH,eAAe,EAAE,CACf,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,kBAAkB,EACtB,OAAO,CAAC,EAAE,gBAAgB,KACvB,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,sBAAsB,CACzD,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,CAKtB,CAAC;AAEF,QAAA,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAInC,CAAC;AAEH,MAAM,MAAM,yBAAyB,GAAG,aAAa,CACnD,OAAO,+BAA+B,EACtC,qBAAqB,CACtB,CAAC"}
1
+ {"version":3,"file":"updateInterface.d.mts","sourceRoot":"","sources":["../../src/permitted/updateInterface.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,wCAAwC;AAE9E,OAAO,KAAK,EACV,qBAAqB,EACrB,qBAAqB,EAErB,kBAAkB,EAClB,gBAAgB,EACjB,4BAA4B;AAK7B,OAAO,EAAE,KAAK,aAAa,EAAE,8BAA8B;AAgB3D,MAAM,MAAM,0BAA0B,GAAG;IACvC;;;;OAIG;IACH,eAAe,EAAE,CACf,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,kBAAkB,EACtB,OAAO,CAAC,EAAE,gBAAgB,KACvB,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,sBAAsB,CACzD,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,CAKtB,CAAC;AAEF,QAAA,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAInC,CAAC;AAEH,MAAM,MAAM,yBAAyB,GAAG,aAAa,CACnD,OAAO,+BAA+B,EACtC,qBAAqB,CACtB,CAAC"}
@@ -160,6 +160,7 @@ declare const DialogParametersStruct: import("@metamask/superstruct").Struct<{
160
160
  } | import("@metamask/snaps-sdk/jsx").SnapElement<{
161
161
  src: string;
162
162
  alt?: string | undefined;
163
+ borderRadius?: "none" | "medium" | "full" | undefined;
163
164
  }, "Image"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
164
165
  name: string;
165
166
  value?: string | undefined;
@@ -261,6 +262,7 @@ declare const DialogParametersStruct: import("@metamask/superstruct").Struct<{
261
262
  } | import("@metamask/snaps-sdk/jsx").SnapElement<{
262
263
  src: string;
263
264
  alt?: string | undefined;
265
+ borderRadius?: "none" | "medium" | "full" | undefined;
264
266
  }, "Image"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
265
267
  name: string;
266
268
  value?: string | undefined;
@@ -363,6 +365,7 @@ declare const DialogParametersStruct: import("@metamask/superstruct").Struct<{
363
365
  } | import("@metamask/snaps-sdk/jsx").SnapElement<{
364
366
  src: string;
365
367
  alt?: string | undefined;
368
+ borderRadius?: "none" | "medium" | "full" | undefined;
366
369
  }, "Image"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
367
370
  name: string;
368
371
  value?: string | undefined;
@@ -463,6 +466,7 @@ declare const DialogParametersStruct: import("@metamask/superstruct").Struct<{
463
466
  } | import("@metamask/snaps-sdk/jsx").SnapElement<{
464
467
  src: string;
465
468
  alt?: string | undefined;
469
+ borderRadius?: "none" | "medium" | "full" | undefined;
466
470
  }, "Image"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
467
471
  name: string;
468
472
  value?: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.d.cts","sourceRoot":"","sources":["../../src/restricted/dialog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8BAA8B,EAC9B,uBAAuB,EAExB,wCAAwC;AACzC,OAAO,EAAE,cAAc,EAAe,wCAAwC;AAE9E,OAAO,EACL,UAAU,EAIX,4BAA4B;AAC7B,OAAO,KAAK,EACV,YAAY,EAEZ,cAAc,EACd,MAAM,EAEN,kBAAkB,EAClB,gBAAgB,EAChB,WAAW,EACZ,4BAA4B;AAC7B,OAAO,KAAK,EAAE,aAAa,EAAE,8BAA8B;AAC3D,OAAO,KAAK,EAAE,KAAK,EAAE,8BAA8B;AAEnD,OAAO,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,wBAAwB;AAG3D,OAAO,EAAE,KAAK,iBAAiB,EAAE,qBAAiB;AAElD,QAAA,MAAM,UAAU,gBAAgB,CAAC;AAEjC,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG;IAC7D,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;;;CAKjC,CAAC;AAEF,QAAA,MAAM,iBAAiB,kEAAkC,CAAC;AAE1D,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE1D,KAAK,0BAA0B,GAAG;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE;QACX,EAAE,EAAE,MAAM,CAAC;QACX,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH,CAAC;AAEF,KAAK,mBAAmB,GAAG,CACzB,IAAI,EAAE,0BAA0B,KAC7B,OAAO,CAAC,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC;AAE7C,KAAK,eAAe,GAAG,CACrB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,gBAAgB,EAC1B,WAAW,CAAC,EAAE,WAAW,KACtB,OAAO,CAAC,MAAM,CAAC,CAAC;AAErB,KAAK,YAAY,GAAG,CAClB,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,KACP;IAAE,OAAO,EAAE,kBAAkB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,cAAc,CAAA;CAAE,CAAC;AAE5E,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;;;;;;OAQG;IACH,mBAAmB,EAAE,mBAAmB,CAAC;IAEzC;;;OAGG;IACH,eAAe,EAAE,eAAe,CAAC;IACjC;;;OAGG;IACH,YAAY,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEF,KAAK,iCAAiC,GAAG;IACvC,cAAc,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;IACxD,WAAW,EAAE,iBAAiB,CAAC;CAChC,CAAC;AA8CF,eAAO,MAAM,aAAa;;;wBA3CR,eAAe,gBAAgB;oBACnC,iBAAiB;8BACP,WAAW,8BAA8B,CAAC;wBAChD,SAAS,cAAc,MAAM,CAAC,CAAC,GAAG,IAAI;;;EA4C7C,CAAC;AAsEZ,QAAA,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YA/G5B;;;;;;;;;;;;;eAaG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAbH;;;;;;;;;;;;;eAaG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAbH;;;;;;;;;;;;;eAaG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAbH;;;;;;;;;;;;;eAaG;;;;;;;;;;;;;;;;;;;;;;;;;;;QAqHD,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,aAAa,CAC1C,OAAO,sBAAsB,EAC7B,YAAY,CACb,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,mBAAmB,EACnB,eAAe,EACf,YAAY,GACb,EAAE,iBAAiB,UAEV,wBAAwB,gBAAgB,CAAC,KAC9C,QAAQ,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC,CAoD3C"}
1
+ {"version":3,"file":"dialog.d.cts","sourceRoot":"","sources":["../../src/restricted/dialog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8BAA8B,EAC9B,uBAAuB,EAExB,wCAAwC;AACzC,OAAO,EAAE,cAAc,EAAe,wCAAwC;AAE9E,OAAO,EACL,UAAU,EAIX,4BAA4B;AAC7B,OAAO,KAAK,EACV,YAAY,EAEZ,cAAc,EACd,MAAM,EAEN,kBAAkB,EAClB,gBAAgB,EAChB,WAAW,EACZ,4BAA4B;AAC7B,OAAO,KAAK,EAAE,aAAa,EAAE,8BAA8B;AAC3D,OAAO,KAAK,EAAE,KAAK,EAAE,8BAA8B;AAEnD,OAAO,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,wBAAwB;AAG3D,OAAO,EAAE,KAAK,iBAAiB,EAAE,qBAAiB;AAElD,QAAA,MAAM,UAAU,gBAAgB,CAAC;AAEjC,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG;IAC7D,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;;;CAKjC,CAAC;AAEF,QAAA,MAAM,iBAAiB,kEAAkC,CAAC;AAE1D,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE1D,KAAK,0BAA0B,GAAG;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE;QACX,EAAE,EAAE,MAAM,CAAC;QACX,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH,CAAC;AAEF,KAAK,mBAAmB,GAAG,CACzB,IAAI,EAAE,0BAA0B,KAC7B,OAAO,CAAC,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC;AAE7C,KAAK,eAAe,GAAG,CACrB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,gBAAgB,EAC1B,WAAW,CAAC,EAAE,WAAW,KACtB,OAAO,CAAC,MAAM,CAAC,CAAC;AAErB,KAAK,YAAY,GAAG,CAClB,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,KACP;IAAE,OAAO,EAAE,kBAAkB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,cAAc,CAAA;CAAE,CAAC;AAE5E,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;;;;;;OAQG;IACH,mBAAmB,EAAE,mBAAmB,CAAC;IAEzC;;;OAGG;IACH,eAAe,EAAE,eAAe,CAAC;IACjC;;;OAGG;IACH,YAAY,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEF,KAAK,iCAAiC,GAAG;IACvC,cAAc,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;IACxD,WAAW,EAAE,iBAAiB,CAAC;CAChC,CAAC;AA8CF,eAAO,MAAM,aAAa;;;wBA3CR,eAAe,gBAAgB;oBACnC,iBAAiB;8BACP,WAAW,8BAA8B,CAAC;wBAChD,SAAS,cAAc,MAAM,CAAC,CAAC,GAAG,IAAI;;;EA4C7C,CAAC;AAsEZ,QAAA,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YA/G5B;;;;;;;;;;;;;eAaG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAbH;;;;;;;;;;;;;eAaG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAbH;;;;;;;;;;;;;eAaG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAbH;;;;;;;;;;;;;eAaG;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAqHD,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,aAAa,CAC1C,OAAO,sBAAsB,EAC7B,YAAY,CACb,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,mBAAmB,EACnB,eAAe,EACf,YAAY,GACb,EAAE,iBAAiB,UAEV,wBAAwB,gBAAgB,CAAC,KAC9C,QAAQ,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC,CAoD3C"}