Mensaje de error
Invalid primary type `Email` must be one of `["EIP712Domain","Mail"]`.
Los nombres entre comillas invertidas son tu `primaryType` y los tipos disponibles. viem 2.57 lo lanza con `err.name` «BaseError»; `err.shortMessage` es el texto de arriba, y `err.message` añade una sugerencia, un enlace a la documentación («typeddatainvalidprimarytypeerror») y la versión de viem.
viem (TypeScript) — hashTypedData / signTypedData / verifyTypedData / recoverTypedDataAddress
Qué significa
El `primaryType` que pasas no es una de las claves de `types` (viem añade `EIP712Domain` a la lista que muestra). EIP-712 calcula el hash del mensaje como una instancia del tipo primario, así que viem se niega a adivinar. Los datos tipados en sí pueden estar bien; lo que no existe en ellos es el nombre del struct que se firma.
Por qué ocurre
Se cambió el nombre del struct en un solo lado
frecuenteEl contrato o el backend cambió el nombre `Mail` por `Email` (o `Order` por `OrderV2`) y el frontend sigue enviando el nombre antiguo, o al revés. Como el nombre del tipo forma parte del hash del tipo, ambos lados deben cambiar a la vez de todos modos.
primaryType omitido o sin definir
ocasionalLas cargas útiles construidas dinámicamente (por ejemplo, a partir de JSON) en las que nunca se estableció `primaryType` producen `Invalid primary type \`undefined\``.
Mayúsculas y minúsculas distintas
ocasional`mail` frente a `Mail`: en EIP-712, los nombres de tipo distinguen entre mayúsculas y minúsculas.
Cómo solucionarlo
- 1.
Declarar los tipos con as const
Con `as const`, los tipos de viem convierten `primaryType` en una unión de los nombres de tus structs, así que una discrepancia falla al compilar en lugar de al firmar.
ts const types = { Mail: [ { name: "to", type: "address" }, { name: "contents", type: "string" }, ], } as const; // "as const" lets TypeScript reject a wrong primaryType at compile time const signature = await walletClient.signTypedData({ account, domain, types, primaryType: "Mail", message });