{"version":3,"file":"dialog.mjs","sourceRoot":"","sources":["../../src/restricted/dialog.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n  PermissionSpecificationBuilder,\n  RestrictedMethodOptions,\n  ValidPermissionSpecification,\n} from '@metamask/permission-controller';\nimport { PermissionType, SubjectType } from '@metamask/permission-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport {\n  DialogType,\n  enumValue,\n  ComponentOrElementStruct,\n  selectiveUnion,\n} from '@metamask/snaps-sdk';\nimport type {\n  DialogParams,\n  Component,\n  InterfaceState,\n  SnapId,\n  PromptDialog,\n  ComponentOrElement,\n  InterfaceContext,\n  ContentType,\n} from '@metamask/snaps-sdk';\nimport type { InferMatching } from '@metamask/snaps-utils';\nimport type { Infer } from '@metamask/superstruct';\nimport { create, object, optional, size, string } from '@metamask/superstruct';\nimport type { Json, NonEmptyArray } from '@metamask/utils';\nimport { hasProperty, isObject, isPlainObject } from '@metamask/utils';\n\nimport { type MethodHooksObject } from '../utils';\n\nconst methodName = 'snap_dialog';\n\nexport type DialogApprovalTypes = Record<DialogType, string> & {\n  default: string;\n};\n\nexport const DIALOG_APPROVAL_TYPES = {\n  [DialogType.Alert]: `${methodName}:alert`,\n  [DialogType.Confirmation]: `${methodName}:confirmation`,\n  [DialogType.Prompt]: `${methodName}:prompt`,\n  default: methodName,\n};\n\nconst PlaceholderStruct = optional(size(string(), 1, 40));\n\nexport type Placeholder = Infer<typeof PlaceholderStruct>;\n\ntype RequestUserApprovalOptions = {\n  id?: string;\n  origin: string;\n  type: string;\n  requestData: {\n    id: string;\n    placeholder?: string;\n  };\n};\n\ntype RequestUserApproval = (\n  opts: RequestUserApprovalOptions,\n) => Promise<boolean | null | string | Json>;\n\ntype CreateInterface = (\n  snapId: string,\n  content: ComponentOrElement,\n  context?: InterfaceContext,\n  contentType?: ContentType,\n) => Promise<string>;\n\ntype GetInterface = (\n  snapId: string,\n  id: string,\n) => { content: ComponentOrElement; snapId: SnapId; state: InterfaceState };\n\nexport type DialogMethodHooks = {\n  /**\n   * @param opts - The `requestUserApproval` options.\n   * @param opts.id - The approval ID. If not provided, a new approval ID will be generated.\n   * @param opts.origin - The origin of the request. In this case, the Snap ID.\n   * @param opts.type - The type of the approval request.\n   * @param opts.requestData - The data of the approval request.\n   * @param opts.requestData.id - The ID of the interface.\n   * @param opts.requestData.placeholder - The placeholder of the `Prompt` dialog.\n   */\n  requestUserApproval: RequestUserApproval;\n\n  /**\n   * @param snapId - The Snap ID creating the interface.\n   * @param content - The content of the interface.\n   */\n  createInterface: CreateInterface;\n  /**\n   * @param snapId - The SnapId requesting the interface.\n   * @param id - The interface ID.\n   */\n  getInterface: GetInterface;\n};\n\ntype DialogSpecificationBuilderOptions = {\n  allowedCaveats?: Readonly<NonEmptyArray<string>> | null;\n  methodHooks: DialogMethodHooks;\n};\n\ntype DialogSpecification = ValidPermissionSpecification<{\n  permissionType: PermissionType.RestrictedMethod;\n  targetName: typeof methodName;\n  methodImplementation: ReturnType<typeof getDialogImplementation>;\n  allowedCaveats: Readonly<NonEmptyArray<string>> | null;\n}>;\n\n/**\n * The specification builder for the `snap_dialog` permission. `snap_dialog`\n * lets the Snap display one of the following dialogs to the user:\n * - An alert, for displaying information.\n * - A confirmation, for accepting or rejecting some action.\n * - A prompt, for inputting some information.\n *\n * @param options - The specification builder options.\n * @param options.allowedCaveats - The optional allowed caveats for the\n * permission.\n * @param options.methodHooks - The RPC method hooks needed by the method\n * implementation.\n * @returns The specification for the `snap_dialog` permission.\n */\nconst specificationBuilder: PermissionSpecificationBuilder<\n  PermissionType.RestrictedMethod,\n  DialogSpecificationBuilderOptions,\n  DialogSpecification\n> = ({\n  allowedCaveats = null,\n  methodHooks,\n}: DialogSpecificationBuilderOptions) => {\n  return {\n    permissionType: PermissionType.RestrictedMethod,\n    targetName: methodName,\n    allowedCaveats,\n    methodImplementation: getDialogImplementation(methodHooks),\n    subjectTypes: [SubjectType.Snap],\n  };\n};\n\nconst methodHooks: MethodHooksObject<DialogMethodHooks> = {\n  requestUserApproval: true,\n  createInterface: true,\n  getInterface: true,\n};\n\nexport const dialogBuilder = Object.freeze({\n  targetName: methodName,\n  specificationBuilder,\n  methodHooks,\n} as const);\n\nconst AlertParametersWithContentStruct = object({\n  type: enumValue(DialogType.Alert),\n  content: ComponentOrElementStruct,\n});\n\nconst AlertParametersWithIdStruct = object({\n  type: enumValue(DialogType.Alert),\n  id: string(),\n});\n\nconst AlertParametersStruct = selectiveUnion((value) => {\n  if (isPlainObject(value) && hasProperty(value, 'id')) {\n    return AlertParametersWithIdStruct;\n  }\n  return AlertParametersWithContentStruct;\n});\n\nconst ConfirmationParametersWithContentStruct = object({\n  type: enumValue(DialogType.Confirmation),\n  content: ComponentOrElementStruct,\n});\n\nconst ConfirmationParametersWithIdStruct = object({\n  type: enumValue(DialogType.Confirmation),\n  id: string(),\n});\n\nconst ConfirmationParametersStruct = selectiveUnion((value) => {\n  if (isPlainObject(value) && hasProperty(value, 'id')) {\n    return ConfirmationParametersWithIdStruct;\n  }\n  return ConfirmationParametersWithContentStruct;\n});\n\nconst PromptParametersWithContentStruct = object({\n  type: enumValue(DialogType.Prompt),\n  content: ComponentOrElementStruct,\n  placeholder: PlaceholderStruct,\n});\n\nconst PromptParametersWithIdStruct = object({\n  type: enumValue(DialogType.Prompt),\n  id: string(),\n  placeholder: PlaceholderStruct,\n});\n\nconst PromptParametersStruct = selectiveUnion((value) => {\n  if (isPlainObject(value) && hasProperty(value, 'id')) {\n    return PromptParametersWithIdStruct;\n  }\n  return PromptParametersWithContentStruct;\n});\n\nconst DefaultParametersWithContentStruct = object({\n  content: ComponentOrElementStruct,\n});\n\nconst DefaultParametersWithIdStruct = object({\n  id: string(),\n});\n\nconst DefaultParametersStruct = selectiveUnion((value) => {\n  if (isPlainObject(value) && hasProperty(value, 'id')) {\n    return DefaultParametersWithIdStruct;\n  }\n  return DefaultParametersWithContentStruct;\n});\n\nconst DialogParametersStruct = selectiveUnion((value) => {\n  if (isPlainObject(value) && hasProperty(value, 'type')) {\n    switch (value.type) {\n      // We cannot use typedUnion here unfortunately.\n      case DialogType.Alert:\n        return AlertParametersStruct;\n      case DialogType.Confirmation:\n        return ConfirmationParametersStruct;\n      case DialogType.Prompt:\n        return PromptParametersStruct;\n      default:\n        throw new Error(\n          `The \"type\" property must be one of: ${Object.values(DialogType).join(\n            ', ',\n          )}.`,\n        );\n    }\n  }\n  return DefaultParametersStruct;\n});\n\nexport type DialogParameters = InferMatching<\n  typeof DialogParametersStruct,\n  DialogParams\n>;\n\n/**\n * Builds the method implementation for `snap_dialog`.\n *\n * @param hooks - The RPC method hooks.\n * @param hooks.requestUserApproval - A function that creates a new Approval in the ApprovalController.\n * This function should return a Promise that resolves with the appropriate value when the user has approved or rejected the request.\n * @param hooks.createInterface - A function that creates the interface in SnapInterfaceController.\n * @param hooks.getInterface - A function that gets an interface from SnapInterfaceController.\n * @returns The method implementation which return value depends on the dialog\n * type, valid return types are: string, boolean, null.\n */\nexport function getDialogImplementation({\n  requestUserApproval,\n  createInterface,\n  getInterface,\n}: DialogMethodHooks) {\n  return async function dialogImplementation(\n    args: RestrictedMethodOptions<DialogParameters>,\n  ): Promise<boolean | null | string | Json> {\n    const {\n      params,\n      context: { origin },\n    } = args;\n\n    if (!isObject(params)) {\n      throw rpcErrors.invalidParams({\n        message: 'Invalid params: Expected params to be a single object.',\n      });\n    }\n\n    const validatedParams = getValidatedParams(params);\n    const placeholder = isPromptDialog(validatedParams)\n      ? validatedParams.placeholder\n      : undefined;\n\n    const validatedType = hasProperty(validatedParams, 'type')\n      ? validatedParams.type\n      : 'default';\n\n    const approvalType =\n      DIALOG_APPROVAL_TYPES[\n        validatedType as keyof typeof DIALOG_APPROVAL_TYPES\n      ];\n\n    if (hasProperty(validatedParams, 'content')) {\n      const id = await createInterface(\n        origin,\n        validatedParams.content as Component,\n      );\n\n      return requestUserApproval({\n        id: approvalType === DIALOG_APPROVAL_TYPES.default ? id : undefined,\n        origin,\n        type: approvalType,\n        requestData: { id, placeholder },\n      });\n    }\n\n    validateInterface(origin, validatedParams.id, getInterface);\n\n    return requestUserApproval({\n      id:\n        approvalType === DIALOG_APPROVAL_TYPES.default\n          ? validatedParams.id\n          : undefined,\n      origin,\n      type: approvalType,\n      requestData: { id: validatedParams.id, placeholder },\n    });\n  };\n}\n/**\n * Validate that the interface ID is valid.\n *\n * @param origin - The origin of the request.\n * @param id - The interface ID.\n * @param getInterface - The function to get the interface.\n */\nfunction validateInterface(\n  origin: string,\n  id: string,\n  getInterface: GetInterface,\n) {\n  try {\n    getInterface(origin, id);\n  } catch (error) {\n    throw rpcErrors.invalidParams({\n      message: `Invalid params: ${error.message}`,\n    });\n  }\n}\n\n/**\n * Gets the dialog type from the dialog parameters.\n *\n * @param params - The dialog parameters.\n * @returns The dialog type.\n */\nfunction getDialogType(params: DialogParameters): DialogType | undefined {\n  return hasProperty(params, 'type') ? (params.type as DialogType) : undefined;\n}\n\n/**\n * Checks if the dialog parameters are for a prompt dialog.\n *\n * @param params - The dialog parameters.\n * @returns `true` if the dialog parameters are for a prompt dialog, `false` otherwise.\n */\nfunction isPromptDialog(params: DialogParameters): params is PromptDialog {\n  return getDialogType(params) === DialogType.Prompt;\n}\n\n/**\n * Validates the confirm 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 confirm method parameter object.\n */\nfunction getValidatedParams(params: unknown): DialogParameters {\n  try {\n    return create(params, DialogParametersStruct);\n  } catch (error) {\n    throw rpcErrors.invalidParams({\n      message: `Invalid params: ${error.message}`,\n    });\n  }\n}\n"]}