エラーメッセージ
Invalid primary type `Email` must be one of `["EIP712Domain","Mail"]`.
バッククォートで囲まれた名前は、指定した `primaryType` と利用可能な型です。viem 2.57 は `err.name` が「BaseError」のエラーとしてこれをスローします。`err.shortMessage` は上記の文で、`err.message` にはヒント、ドキュメントへのリンク(「typeddatainvalidprimarytypeerror」)、viem のバージョンが追加されます。
viem (TypeScript) — hashTypedData / signTypedData / verifyTypedData / recoverTypedDataAddress
このエラーの意味
渡された `primaryType` が `types` のキーに含まれていません(viem が表示する一覧には `EIP712Domain` が追加されています)。EIP-712 はメッセージをプライマリタイプのインスタンスとしてハッシュするため、viem は推測で補うことはしません。型付きデータ自体には問題がないこともありますが、署名対象の構造体の名前がその中に存在しません。
発生する理由
片方の側で構造体の名前が変更された
よくあるコントラクトやバックエンドで `Mail` を `Email`(または `Order` を `OrderV2`)に変更したのに、フロントエンドが古い名前を送り続けている、あるいはその逆です。型名は型ハッシュの一部なので、いずれにしても両側を同時に変更しなければなりません。
primaryType が省略されている、または undefined
ときどき(たとえば JSON から)動的に組み立てたペイロードで `primaryType` が一度も設定されていない場合は、`Invalid primary type \`undefined\`` となります。
大文字と小文字の違い
ときどき`mail` と `Mail`:EIP-712 の型名では大文字と小文字が区別されます。
修正方法
- 1.
types を as const で宣言する
`as const` を使うと、viem の型定義によって `primaryType` が構造体名のユニオン型になるため、不一致は署名時ではなくコンパイル時にエラーになります。
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 });