Сообщение об ошибке
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` таких типов несколько, поэтому ethers не может понять, какой из них подписывается. На практике лишним почти всегда оказывается `EIP712Domain`: ethers сам строит тип домена из аргумента `domain` и не должен получать его в `types`, тогда как JSON-формат `eth_signTypedData_v4` (MetaMask, WalletConnect) его включает.
Почему это происходит
EIP712Domain остался в types
частоТипизированные данные, скопированные из запроса кошелька, из бэкенда, который формирует полезную нагрузку для `eth_signTypedData_v4`, или из тестовой фикстуры, содержат `EIP712Domain`. ethers считает его вторым корневым типом.
Тип, на который никто не ссылается
иногдаОставшиеся определения структур (например, от старой версии сообщения) тоже становятся корнями и делают основной тип неоднозначным.
Две независимые структуры в одном объекте
иногдаТипы разных сообщений (Order и Cancel) объединены в одном объекте `types`. Передавайте только типы того сообщения, которое подписываете.
Как исправить
- 1.
Удалите EIP712Domain перед вызовом ethers
Отбросьте его деструктуризацией; подпись получится такой же, какую кошелёк создаёт для полезной нагрузки 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);