import { hexToNumber, serializeSignature } from "viem"; import { assertNever } from "../../utils.js"; import type { PersonalSignSignatureRequest, TypedDataSignatureRequest, AuthorizationSignatureRequest, Eip7702UnsignedAuth, EcdsaSig, } from "@alchemy/wallet-api-types"; import { vToYParity } from "ox/Signature"; import type { WithoutRawPayload } from "../../types.ts"; import { metrics } from "../../metrics.js"; import type { SmartWalletSigner } from "../index.js"; export type SignSignatureRequestParams = WithoutRawPayload< | PersonalSignSignatureRequest | TypedDataSignatureRequest | (AuthorizationSignatureRequest & { data: Eip7702UnsignedAuth; }) >; export type SignSignatureRequestResult = EcdsaSig["signature"]; /** * Signs a signature request using the provided signer. * This method handles different types of signature requests including personal_sign, eth_signTypedData_v4, and authorization. * * @param {SmartAccountSigner} signer - The signer to use for signing the request * @param {SignSignatureRequestParams} params - The signature request parameters * @param {string} params.type - The type of signature request ('personal_sign', 'eth_signTypedData_v4', or 'signature_with_authorization') * @param {SignSignatureRequestParams["data"]} params.data - The data to sign, format depends on the signature type * @returns {Promise} A Promise that resolves to the signature result * * @example * ```ts * // Sign a personal message * const result = await client.signSignatureRequest({ * type: 'personal_sign', * data: 'Hello, world!' * }); * * // Sign typed data (EIP-712) * const result = await client.signSignatureRequest({ * type: 'eth_signTypedData_v4', * data: { * domain: { ... }, * types: { ... }, * primaryType: '...', * message: { ... } * } * }); * ``` */ export async function signSignatureRequest( signer: SmartWalletSigner, params: SignSignatureRequestParams, ): Promise { metrics.trackEvent({ name: "sign_signature_request", data: { type: params.type, }, }); switch (params.type) { case "personal_sign": { return { type: "secp256k1", data: await signer.signMessage(params.data), }; } case "eth_signTypedData_v4": { return { type: "secp256k1", data: await signer.signTypedData(params.data), }; } case "eip7702Auth": { if (!signer.signAuthorization) { throw new Error("Signer does not implement signAuthorization"); } const { r, s, v, yParity: _yParity, } = await signer.signAuthorization({ ...params.data, chainId: hexToNumber(params.data.chainId), nonce: hexToNumber(params.data.nonce), }); const yParity = _yParity != null ? Number(_yParity) : vToYParity(Number(v)); return { type: "secp256k1", data: serializeSignature({ r, s, yParity, }), }; } default: return assertNever(params, `Unexpected signature request type.`); } }