エラーメッセージ
ambiguous primary types or unused types: "EIP712Domain", "Mail"
別の表記
- ambiguous primary types or unused types
列挙される名前は、参照されていない型です。`err.message` には `types` の値全体と ethers のバージョンも含まれ、`err.code` は `INVALID_ARGUMENT` です。
ethers v6 (JavaScript) — TypedDataEncoder used by signTypedData / verifyTypedData
このエラーの意味
ethers は、EIP-712 の型付きデータのプライマリタイプを、ほかのどの型からも参照されていない唯一の型として推定します。渡された `types` オブジェクトには参照されていない型が複数あるため、どれが署名対象なのか判断できません。実際には、余分な型はほぼ必ず `EIP712Domain` です。ethers はドメインの型を `domain` 引数から自分で組み立てるため、`types` に含めて渡してはいけません。一方、`eth_signTypedData_v4` の JSON 形式(MetaMask、WalletConnect)にはこの型が含まれています。
発生する理由
types に EIP712Domain が残っている
よくあるウォレットへのリクエスト、`eth_signTypedData_v4` のペイロードを生成するバックエンド、テストフィクスチャからコピーした型付きデータには `EIP712Domain` が含まれています。ethers はこれを 2 つ目のルート型として扱います。
どこからも参照されていない型
ときどき残っている構造体の定義(たとえば古いバージョンのメッセージのもの)もルートとなり、プライマリタイプが曖昧になります。
1 つのオブジェクトに独立した 2 つの構造体
ときどき別々のメッセージ(Order と Cancel)の型が 1 つの `types` オブジェクトにまとめられています。署名するメッセージの型だけを渡してください。
修正方法
- 1.
ethers を呼び出す前に EIP712Domain を削除する
分割代入で取り除いてください。ドメインの型は同じフィールドから導出されるため、署名は v4 のペイロードに対してウォレットが生成するものと同一になります。
js const { EIP712Domain, ...types } = typedData.types; // ethers derives the domain type itself const signature = await signer.signTypedData(typedData.domain, types, typedData.message); const signer2 = verifyTypedData(typedData.domain, types, typedData.message, signature); - 2.
推定されたプライマリタイプを確認する
`TypedDataEncoder.from(types).primaryType` は、同じエラーをスローするか、ethers がハッシュする型を返します。テストで手軽に確認できます。
js import { TypedDataEncoder } from "ethers"; // Inspect what ethers considers the primary type before signing. console.log(TypedDataEncoder.from(types).primaryType);